2009-02-23 34 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()方法來測試邊界屬性。