Полиморфные перечисления для обработки состояний
Как я могу обрабатывать перечисления без использования операторов switch или if в 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 и сделать его универсальным.
Для определенной цены метод вызывает определенный расчет и возвращает его.
get { return CalculatedPrice(Pricemethod); }
Какой шаблон использовать здесь, и, возможно, у кого-то есть хорошая идея реализации. Я уже искал образец состояния, но не думаю, что это правильный.
2 ответа:
Перечисления-это просто приятный синтаксис для написанияКак я могу обрабатывать перечисления без использования операторов
switch
илиif
В C#?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;
Вы можете создать
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); } } }
Edit: другой способ - использовать
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); } } }