«Перечисление как неизменяемый богатый объект»: это антипаттерн?

Я часто видел и использовал перечисления с прикрепленными атрибутами для выполнения некоторых основных действий, таких как предоставление отображаемого имени или description:

public enum Movement {
    [DisplayName("Turned Right")]
    TurnedRight,
    [DisplayName("Turned Left")]
    [Description("Execute 90 degree turn to the left")]
    TurnedLeft,
    // ...
}

И у вас есть набор методов расширения для поддержки атрибутов:

public static string GetDisplayName(this Movement movement) { ... }
public static Movement GetNextTurn(this Movement movement, ...)  { ... }

Следуя этому шаблону, дополнительные существующие или настраиваемые атрибуты могут быть применены к полям для других целей. Это похоже на то, как если бы перечисление могло работать как простой тип перечисляемого значения, которым оно является, и как более богатый объект неизменяемого значения с рядом полей:

public class Movement
{
    public int Value { get; set; } // i.e. the type backing the enum
    public string DisplayName { get; set; }
    public string Description { get; set; }
    public Movement GetNextTurn(...) { ... }
    // ...
}

Таким образом, оно может «перемещаться» как простое поле во время сериализации, Быстро сравнивать и т. д., но поведение можно «усвоить» (аля ООП).

Тем не менее, я понимаю, что это можно рассматривать как антипаттерн. В то же время часть меня считает это достаточно полезным, чтобы анти мог быть слишком строгим.

15
задан Kit 24 October 2011 в 20:57
поделиться