验证属性中的值
本文关键字:属性 验证 | 更新日期: 2023-09-27 18:08:00
我听说像这样验证属性中的值:
//dummy example, let's assume that I want my value without dots
public string MyProp
{
set
{
if(value.Contains('.'))
throw new ArgumentException("Must not contain '.'", "value");
}
}
是错误的,我应该避免它。
但在早些时候,我被告知这是一个好方法。我们可以使用封装,只有一个地方需要检查,DRY,等等。
我的小例子有什么问题吗?
在属性设置器中抛出异常并没有错。但是你应该抛出一个ArgumentException
,并实际设置属性的值!
private string _myprop;
public string MyProp{
set{
if(value.Contains('.')) throw new ArgumentException("Must not contain .");
this._myprop=value;
}
get { return this._myprop; }
}
摘自一篇关于MSDN最佳实践的文章:
属性getter应该是没有任何前提条件的简单操作。如果getter可能抛出异常,请考虑将属性重新设计为方法。此建议不适用于索引器。索引器可能会因为无效参数而抛出异常。
从属性设置器抛出异常是有效且可接受的。
在SO上也有一些类似的问题。
你的属性应该尽可能是轻量级的。如果setter抛出一个错误,这是可以的,但是你可能会考虑把它移到一个函数。事情很容易变得一团糟。
最佳实践:从属性 抛出异常避免从属性获取器抛出异常。财产getter应该是简单的操作,不应该有先决条件。如果一个Getter会抛出异常,它应该被重新设计成方法。
从属性设置器抛出什么异常?
关于为什么从属性抛出异常不好的解释和讨论,请参见:最佳实践:从属性抛出异常。
不可否认,这篇文章谈到了属性getter。
setter通常被消费者视为简单地设置由属性隐藏的私有字段,并可能根据需要做一些额外的事情,异常是意想不到的行为,你能想象必须将每个set语句包含在try块中吗?
虽然这可能是准则所接受的行为,但对于开发人员来说,猜测它是一场噩梦,并且验证逻辑应该包含在一个单独的方法中,然后在需要时从属性中调用。
如果你在设置属性时需要验证或特殊行为,你应该使用set方法,例如SetMyProp(string value)
,因为它带来了一个区别,它可能导致异常等
如果你正在使用属性,比如WPF模型,那么你应该使用WPF内置的数据验证。