2013-10-22 90 views
6

我如何處理枚舉而不使用開關或在C#語句?狀態處理的多態引用

對於實例

enum Pricemethod 
{ 
    Max, 
    Min, 
    Average 
} 

...我有一類文章

public class Article 
{ 
    private List<Double> _pricehistorie; 

    public List<Double> Pricehistorie 
    { 
     get { return _pricehistorie; } 
     set { _pricehistorie = value; } 
    } 

    public Pricemethod Pricemethod { get; set; } 

    public double Price 
    { 
     get { 
      switch (Pricemethod) 
      { 
       case Pricemethod.Average: return Average(); 
       case Pricemethod.Max: return Max(); 
       case Pricemethod.Min: return Min(); 
      } 

     } 
    } 

} 

我想要避免switch語句,並使它通用。

對於特定的Pricemethod調用特定的計算並將其返回。

get { return CalculatedPrice(Pricemethod); } 

這種模式是用在這裏,也許有人有一個很好的實現的想法。 已經搜索了狀態模式,但我不認爲這是正確的。實現它

+5

價格應該是'decimal',不'double'。使用「double」來表示長度和質量等物理量;精確的小數量使用'decimal'。 –

+0

您是否打算返回**可變**的價格集合?什麼是阻止您的方法的調用者在該清單上調用「清除」? –

+0

那麼你用_strategy-pattern_標記了這個嗎?這幾乎是這裏的答案... –

回答

11

如何處理枚舉,而無需使用C#中的或if語句?

你不知道。枚舉只是編寫const int的一個令人愉快的語法。

考慮這樣的模式:

public abstract class PriceMethod 
{ 
    // Prevent inheritance from outside. 
    private PriceMethod() {} 

    public abstract decimal Invoke(IEnumerable<decimal> sequence); 

    public static PriceMethod Max = new MaxMethod(); 

    private sealed class MaxMethod : PriceMethod 
    { 
    public override decimal Invoke(IEnumerable<decimal> sequence) 
    { 
     return sequence.Max(); 
    } 
    } 

    // etc, 
} 

現在你可以說

public decimal Price 
{ 
    get { return PriceMethod.Invoke(this.PriceHistory); } 
} 

,用戶可以說

myArticle.PriceMethod = PriceMethod.Max; 
decimal price = myArticle.Price; 
+0

將此標記爲正確的答案,因爲在這篇文章中eric的整體學習! – slopsucker

+0

這看起來像策略設計模式。 – Brian

+0

@布萊恩:如果「讓一個有你想做的方法的對象」被模式愛好者稱爲「策略模式」,那麼當然,這是策略模式。由於每個只有一個,它也是單例模式。它也可能是工廠模式。也許還有其他幾種模式。我無法讓他們全部直行。 –

5

您可以創建一個interfaceclass ES:

public interface IPriceMethod 
{ 
    double Calculate(IList<double> priceHistorie); 
} 
public class AveragePrice : IPriceMethod 
{ 
    public double Calculate(IList<double> priceHistorie) 
    { 
     return priceHistorie.Average(); 
    } 
} 
// other classes 
public class Article 
{ 
    private List<Double> _pricehistorie; 

    public List<Double> Pricehistorie 
    { 
     get { return _pricehistorie; } 
     set { _pricehistorie = value; } 
    } 

    public IPriceMethod Pricemethod { get; set; } 

    public double Price 
    { 
     get { 
      return Pricemethod.Calculate(Pricehistorie); 
     } 
    } 

} 

編輯:另一種方法是使用Dictionary映射Func S,所以你不必創建只爲這班(這個代碼是基於Servy代碼,因爲誰刪除了他的答案):

public class Article 
{ 
    private static readonly Dictionary<Pricemethod, Func<IEnumerable<double>, double>> 
     priceMethods = new Dictionary<Pricemethod, Func<IEnumerable<double>, double>> 
     { 
      {Pricemethod.Max,ph => ph.Max()}, 
      {Pricemethod.Min,ph => ph.Min()}, 
      {Pricemethod.Average,ph => ph.Average()}, 
     }; 

    public Pricemethod Pricemethod { get; set; } 
    public List<Double> Pricehistory { get; set; } 

    public double Price 
    { 
     get 
     { 
      return priceMethods[Pricemethod](Pricehistory); 
     } 
    } 
} 
+0

看起來不錯,而且有效。塔克你!但是,是不是有一個更聰明的方法,而不是實施噸有1種方法的類? – slopsucker

+0

@slopsucker我已經添加了一個例子。 –

+0

我仍然更喜歡Interface解決方案。如果您將來需要添加新的計算方法,則無需觸摸您的文章類。是的,你會得到更多的課程,但它會更孤立,更容易維持我的想法。第二種解決方案與開關和枚舉幾乎相同。 –