2009-02-23 67 views
1

是否有一种简洁的方式来表示.NET 3.5中有界的数值?由此我的意思是诸如百分比(0-100)概率(0-1)或库存水平(0或以上)的值。表示一个百分比,概率或库存水平

我想要一个ArgumentOutOfRangeException(或等效)抛出如果超出范围的任务尝试。我也希望静态MaxValueMinValue属性可用。

comment to another SO question中建议,这是struct的良好用法。

回答

4

我不认为有喜欢小梅"range" keyword一个内置的方式,但你可以很容易地创建一个类型像RestrictedRange <牛逼>这同当前值一起最低和最高值:

public class RestrictedRange<T> where T : IComparable 
{   
    private T _Value; 

    public T MinValue { get; private set; } 
    public T MaxValue { get; private set; } 

    public RestrictedRange(T minValue, T maxValue) 
     : this(minValue, maxValue, minValue) 
    { 
    } 

    public RestrictedRange(T minValue, T maxValue, T value) 
    { 
     if (minValue.CompareTo(maxValue) > 0) 
     { 
      throw new ArgumentOutOfRangeException("minValue"); 
     } 

     this.MinValue = minValue; 
     this.MaxValue = maxValue; 
     this.Value = value; 
    } 

    public T Value 
    { 
     get 
     { 
      return _Value; 
     } 

     set 
     { 
      if ((0 < MinValue.CompareTo(value)) || (MaxValue.CompareTo(value) < 0)) 
      { 
       throw new ArgumentOutOfRangeException("value"); 
      } 
      _Value = value; 
     } 
    } 

    public static implicit operator T(RestrictedRange<T> value) 
    { 
     return value.Value; 
    }   

    public override string ToString() 
    { 
     return MinValue + " <= " + Value + " <= " + MaxValue; 
    } 
} 

由于存在隐式转换为自动获取的价值,这将工作:

var adultAge = new RestrictedRange<int>(18, 130, 21); 
adultAge.Value++; 
int currentAge = adultAge; // = 22 

另外,你可以做这样的事情

var stockLevel = new RestrictedRange<int>(0, 1000) 
var percentage = new RestrictedRange<double>(0.0, 1.0); 
1

事实上,这是用于70-526考试的MS Press学习指南中“用于使用结构的地方”示例的类型。一小组数据(< 16个字节),具有值语义,最好设计为一个结构体,而不是一个类。

1

我可能会创建一个类来表示有界值。

public class Percentage 
{ 
    public static readonly double MinValue = 0.0; 
    public static readonly double MaxValue = 100.0; 

    private double value; 
    public double Value 
    { 
     get { return this.value; } 
     set 
     { 
      if (value < MinValue || value > MaxValue) 
      { 
       throw new ArgumentOutOfRangeException("..."); 
      } 
      this.value = value; 
     } 
} 

如果您的数据存储在数据库中,但是,您通常可以避免这一点,只需使用天然基础类型的值和强制约束的数据库和数据验证方法。如有必要,最小/最大值可以存储在配置中。

+0

+1,只是打我吧... – 2009-02-23 15:30:40

1

当然,您可以通过在setter中检查它们来强制实现类中任何整数属性的边界。但是,这并未明确地向该类用户传达界限要求。我在解决这个问题的一个类似的问题:
How do I indicate a validation requirement to users of my class?

基于这个问题和经验,因为获得了

,我建议你创建一个新的BoundedInteger类。这个类将有一个值属性,这应该是自我解释。它也可以隐式转换为整数或从整数转换,以方便您的类的用户。您还可以将MinValue和MaxValue项添加为只读属性,并将它们作为必需参数包含在您的类构造函数中。

一个重要的补充是,你可能不会总是想抛出一个坏分配的例外,因为有时一个不好的分配可能不是那么例外。根据上下文,有几个行为,你可以选择当一个坏的分配尝试:

  • 允许分配反正(例如:有人可能真的要110%的值)
  • 保留以前的值
  • 复位至零或其他一些“默认”值
  • 将值设置为最近的边界(即,如果他们尝试分配110到百分比,将其设置为100,而不是)

任何的那些行为也可以根据财产的需要抛出异常。根据你的问题领域,这可能都是矫枉过正,但值得记住,当你设计你的程序。

如果您决定确实需要这种灵活性,您可能希望在enum中定义这些行为,并使用只读属性来保存该值。然后,为默认值选择一个,然后添加一个额外的构造函数,您可以在其中为该实例设置特定的行为,以及是否应抛出异常。最后,如果您要潜在地允许错误的分配,您可能希望提供一个IsValid()方法来测试边界属性。