2013-10-22 12 views
6

C#でswitchまたはif文を使用せずにEnumを処理する方法は?例ステートハンドリング用の多態列挙型

enum Pricemethod 
{ 
    Max, 
    Min, 
    Average 
} 

については

...と私はswitch文を回避し、それが一般的なようにしたいArticleクラス

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(); 
      } 

     } 
    } 

} 

を持っています。

特定のプライスメソッドは、特定の計算を呼び出して返します。

ここで、多分誰かが良い実装のアイディアを持っています。 状態パターンについて既に検索されていますが、これは正しいパターンではないと思います。

+5

価格は 'decimal'、ない' double'べきであると言うことができます。長さや質量などの物理量には 'double'を使います。正確な10進数量のために 'decimal'を使います。 –

+0

**変更可能**価格の回収をご希望ですか?あなたのメソッドの呼び出し元がそのリストで 'Clear'を呼び出すのを止めているのは何ですか? –

+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

@ブライアン:「あなたがしたいことをする方法を持つオブジェクトを作る」がパターン愛好家によって「戦略パターン」と呼ばれている場合は、これが戦略パターンです。それぞれが1つしかないので、シングルトンパターンでもあります。また、工場のパターンかもしれません。そして、おそらくいくつかの他のパタ​​ーン。私はそれらをまっすぐに保つことはできません。 –

5

あなたがinterface、およびそれを実装class 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); 
     } 
    } 

} 

編集:別の方法はFunc SをマップするDictionaryを使用しているので、あなただけのこのためのクラスを作成する必要はありませんが(このコードは、以来、彼の答えを削除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

私はまだインターフェイスソリューションがより好きです。将来、新しい計算メソッドを追加する必要がある場合、Articleクラスに触れる必要はありません。はい、あなたはより多くのクラスで終わるでしょうが、それはもっと孤立していて、私は思ったより保守しやすいでしょう。 2番目の解決方法は、スイッチとEnumを使用する方法とほぼ同じです。 –