【问题标题】:Best way to enforce constraints when constructing an object构造对象时强制执行约束的最佳方法
【发布时间】:2011-07-19 04:07:20
【问题描述】:

我有一个 Prize 对象,它有一个带有单个 int 参数 pence 的构造函数。我不想让负值传入。执行此限制的最佳方法是什么?我应该从构造函数中抛出异常吗?还是写一个工厂方法?

编辑: Prize 对象被用作一般角色的示例。在此特定示例中,使用 uint 是一个很好的答案,而不是一般角色。我使用 3.5 没有额外的代码契约库。

【问题讨论】:

    标签: c#


    【解决方案1】:

    我有一个 Prize 对象,它有一个 具有单个 int 的构造函数 参数便士。我不想让 要传入的负值。

    为什么不使用uint 数据类型来代替pence?那么它已经保证它是一个正值,你不必自己强制执行这个约束。

    通常,对于强制执行约束,口头禅是“fail as soon as possible”(另请参阅fail fast),因此您应该在构造函数中抛出异常或使用@987654322 强制执行您的约束@。我真的不明白工厂方法在这种情况下会有什么帮助。

    【讨论】:

    • 好主意。但是请记住,uint 不符合 CLS(请参阅 msdn.microsoft.com/en-us/library/x0sksh43.aspx)。这是否与您的案件相关取决于您。
    • @nodots:这是很好的信息。我想我需要再次阅读有关数据类型的 C# 规范以进行复习。
    【解决方案2】:

    如何构造实例(ctor 或工厂)的设计选择独立于参数验证。通常,您应该偏爱构造函数(例如,请参阅此答案以获取框架设计指南的相关摘录):

    When to use Factory method pattern?

    验证参数的简单方法当然是抛出适当异常的保护子句:

    public Prize(int pence)
    {
        if (pence < 0)
        {
            throw new ArgumentException(...);
        }
    
        /* Do stuff */
    }
    

    还有Code Contracts,您可能想查看。我认为这些允许您注释您的要求,但我还没有机会尝试它们。

    【讨论】:

      【解决方案3】:

      正如您使用int 而不是string 来强制传入有效整数一样,如果您只需要非负整数,那么使用适当的类型怎么样:uint

      【讨论】:

        【解决方案4】:

        我 100% 同意 BrokenGlass。

        您可以用来在奖品对象上具有 int 属性的一个“技巧”只允许正整数而不将数据类型更改为 uint:

        public class Prize 
        {
            private int _pence = 0;
            public int Pence 
            { 
              get { return _pence; }
              set { _pence = Math.Max(value, 0); }
            }
        
            public Price(int pence) 
            {
                Pence = pence;
            }
        }
        

        这并不能阻止人们在使用你的类时使用反射来设置负数,但它确实会阻止负数被正常输入。

        如果您不想默默地忽略负值,您可以抛出异常,甚至调用Math.Abs

        【讨论】:

          猜你喜欢
          • 2017-01-14
          • 2021-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多