验证属性中的值

本文关键字:属性 验证 | 更新日期: 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内置的数据验证。