【问题标题】:Validate a value in property验证属性中的值
【发布时间】:2013-03-30 21:36:27
【问题描述】:

所以我听说像这样验证属性中的值:

//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 等。

我的小例子有什么问题?

【问题讨论】:

  • 没什么问题,但是 a) 我宁愿抛出一个 ArgumentException,b) 你忘了实际设置值!
  • 你不能只扔一个字符串。你需要抛出一个异常。
  • @jrummell 不重复。在那个问题中,他们不讨论例外情况
  • 这是个好办法。 .NET 框架的几个部分做同样的事情。

标签: c# dry encapsulation


【解决方案1】:

在属性设置器中抛出异常并没有错。但是你应该抛出一个ArgumentException,并且还要实际设置属性的值!

private string _myprop;
public string MyProp{
    set{
       if(value.Contains('.')) throw new ArgumentException("Must not contain .");
       this._myprop=value;
    }
    get { return this._myprop; }
}

来自article on best practices in MSDN

属性获取器应该是没有任何先决条件的简单操作。如果 getter 可能抛出异常,请考虑将属性重新设计为方法。此建议不适用于索引器。索引器可能会因为参数无效而引发异常。

从属性设置器抛出异常是有效且可接受的。

【讨论】:

  • 谢谢!实际上是一个简单的演示示例。
【解决方案2】:

关于 SO 也有一些类似的问题。

你的属性应该尽可能的轻量级。如果 setter 抛出错误,这没关系,但您可能会再次考虑将其移动到函数中。事情很容易变得一团糟。

避免从属性 getter 中抛出异常。属性吸气剂 应该是简单的操作,不应该有先决条件。如果一个 getter 可以抛出异常,它可能应该重新设计为 一种方法。

Best practices: throwing exceptions from properties

What exception to throw from a property setter?

【讨论】:

    【解决方案3】:

    请参阅:Best practices: throwing exceptions from properties,了解为什么从属性中抛出异常是不好的。

    诚然,这篇文章谈到了财产获取者。

    Setter 通常被消费者视为简单地设置一个被属性隐藏的私有字段,并且可能会根据需要执行一些额外的操作,异常是意外行为,您能想象必须将每个 set 语句包含在 try 块中吗?

    虽然它可能是被准则接受的行为,但对于开发人员来说,猜测是一场噩梦,并且验证逻辑应该包含在单独的方法中,然后在需要时从属性中调用。

    如果您在设置属性时需要验证或特殊行为,您应该使用 set 方法,例如SetMyProp(string value) 因为它带来了一个区别,它可能导致异常等。

    如果您将属性用于 WPF 模型之类的东西,那么您应该改用 WPF 的内置数据验证。

    【讨论】:

    • -1 您链接到的文章指出 setters 中的异常是可以的。来自 MSDN:“从属性设置器抛出异常是有效且可接受的。”
    • 您是否发现 setter 执行验证(并引发异常)以强制执行其合同(例如不允许设置空值)的问题?
    • @hatchet 是的,我认为对于 null 值是可以接受的,或者对于值 really 不能采用某种形式的边缘情况,但如果它是一个值在进一步使用的上下文中“错误”,在尝试使用它们时应该发生异常。
    • 当你有文档字符串时为什么要猜测?您在每个 set 语句周围都有一个 try 块的观点类似于在每个 Substring 周围使用一个 try 块,因为您的起始索引可能超出范围。只需检查数据。
    • 我不同意。 setter 抛出异常是完全可以接受的。例如,您将如何处理不允许为空的属性?如果删除 setter,序列化将失败。能够做到Contract.Requires(value != null); 是必不可少的。
    猜你喜欢
    • 2012-09-18
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多