2010-10-12 18 views
5

Se ha hablado de que Enums viola, en general, los principios de Clean Code, por lo que estoy buscando los anti-patrones Enum favoritos y soluciones alternativas para estos.C#: Enum anti-patterns

Por ejemplo, yo he visto código como este:

switch(enumValue) { 
    case myEnum.Value1: 
     // ... 
     break; 
    case myEnum.Value2: 
     // ... 
     break; 
} 

Es un paso mejor que interruptores-declaraciones con cuerdas mágicas, pero esto probablemente podría haberse resuelto mejor con una fábrica, un contenedor u otro patrón .

O incluso la vieja escuela código como este:

if(enumValue == myEnum.Value1) { 
    // ... 
} else if (enumValue == myEnum.Value2) { 
    // ... 
} 

¿Qué otros anti-patrones y mejores implementaciones has experimentado con enumeraciones?

+4

Diccionario better than Enum ?? ¿puedes explicar porque? –

+5

Usted mezcla todo por completo. 'switch' contra enum no está mal por sí mismo. a veces es necesario, por ejemplo, en la fábrica mencionada. – Andrey

+0

Debe usar Dictionary con una clave de una enumeración. De esta forma, obtienes lo mejor de ambos mundos: diccionario fuertemente tipado Y no más declaraciones de cambio largas. – VitalyB

Respuesta

11

Creo que los mensajes son bastante útiles. He escrito un par de extensiones para Enum que han añadido aún más valor a su uso

primer lugar, está el método Descripción extensión

public static class EnumExtensions 
{ 
    public static string Description(this Enum value) 
    { 
     var entries = value.ToString().Split(ENUM_SEPERATOR_CHARACTER); 
     var description = new string[entries.Length]; 
     for (var i = 0; i < entries.Length; i++) 
     { 
      var fieldInfo = value.GetType().GetField(entries[i].Trim()); 
      var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 
      description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim(); 
     } 
     return String.Join(", ", description); 
    } 
    private const char ENUM_SEPERATOR_CHARACTER = ','; 
} 

Esto permitirá mí definir en la enumeración de esta manera:

public enum MeasurementUnitType 
{ 
    [Description("px")] 
    Pixels = 0, 
    [Description("em")] 
    Em = 1, 
    [Description("%")] 
    Percent = 2, 
    [Description("pt")] 
    Points = 3 
} 

Y obtenga la etiqueta haciendo esto: var myLabel = rectangle.widthunit.Description() (eliminando la necesidad de una declaración switch).

Esto devolverá por cierto "px" si rectangle.widthunit = MeasurementUnitType.Pixels o devolverá "px, em" si rectangle.widthunit = MeasurementUnitType.Pixels | MeasurementUnitType.Em.

Entonces, hay una

public static IEnumerable<int> GetIntBasedEnumMembers(Type @enum) 
    { 
     foreach (FieldInfo fi in @enum.GetFields(BindingFlags.Public | BindingFlags.Static)) 
      yield return (int)fi.GetRawConstantValue(); 
    } 

¿Qué me permite atravesar cualquier enumeración con valores basados ​​int y devuelva el int propios valores.

Me parecen muy útiles en un concepto ya útil.

+0

No lo hacemos con un código más corto y más simple con un Dictionary ? ¿Qué valor trae el código anterior? –

+3

@Seb: Varias razones: primero, la descripción está al lado de la declaración en lugar de en otro lugar si usa un diccionario. En segundo lugar, la descripción siempre está presente con el tipo de enumeración, que conduce a ... finalmente, el tipo puede importarse a otro ensamblado y los valores enum y sus descripciones pueden reflejarse y presentarse al usuario (útil para los editores y es algo) Hice). – Skizz

+0

Gracias Skizz, por ahorrarme el tiempo;) Bien hecho. – danijels

0

Usando enums en no anti-patrón. En algunos libros sobre refactorización, este código se usa para demostrar cómo reemplazarlo con polimorfismo. Estaría bien cuando sobreutilizas enums en el código.

+1

Eso no fue lo que se dijo. Pedí antipatrones que implicaran enumeraciones. –

1

Esto no es una respuesta, tanto como contribuir a una lista de antipatrones Enum.

Durante una revisión del código de esta mañana, me encontré con un caso similar al siguiente, todos en la misma clase.

dos casos:

  1. antes de beber
  2. Después de beber

..

public enum ListEnum 
    { 
     CategoryOne, 
     CategoryTwo, 
     CategoryThree, 
     CategoryFour 
    } 


    public class UIELementType 
    { 
     public const string FactoryDomain = "FactoryDomain"; 
     public const string Attributes = "Attributes"; 
    }