2010-10-12 3 views
5

Si è parlato di Enum in generale che violava i principi del Codice pulito, quindi sto cercando gli anti-pattern e le soluzioni alternative di Enum preferite dalle persone per questi.C#: Enum anti-patterns

Per esempio ho visto il codice come questo:

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

E 'un passo migliore di switch-dichiarazioni con le stringhe di magia, ma questo probabilmente avrebbe potuto essere risolto meglio con una fabbrica, un contenitore o altro modello .

O anche vecchia scuola codice come questo:

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

Quali altri anti-pattern e le implementazioni migliori avete sperimentato con enumerazioni?

+4

Dizionario meglio di Enum ?? puoi spiegare perché? –

+5

Mescoli tutto insieme. 'switch' contro enum non è male da solo. a volte è necessario, ad esempio nella fabbrica menzionata. – Andrey

+0

Dovresti usare Dizionario con una chiave di enum. In questo modo ottieni il meglio da entrambi i mondi: un dizionario fortemente tipizzato e niente più dichiarazioni a lungo termine. – VitalyB

risposta

11

Penso che le enumerazioni siano abbastanza utili. Ho scritto un paio di estensioni per Enum che hanno aggiunto ancora più valore al suo uso

In primo luogo, c'è il metodo di descrizione estensione

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 = ','; 
} 

Questo mi permetterà di definire en enum come questo:

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

E ottenere l'etichetta facendo questo: var myLabel = rectangle.widthunit.Description() (eliminando qualsiasi necessità di una dichiarazione switch).

Ciò restituirà "px" se rectangle.widthunit = MeasurementUnitType.Pixels o restituirà "px, em" se rectangle.widthunit = MeasurementUnitType.Pixels | MeasurementUnitType.Em.

Poi, c'è un

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

Il che mi permette di attraversare qualsiasi enum con valori basati int e restituire l'int stessi valori.

Trovo che questi siano molto utili in un concetto già utile.

+0

Non lo facciamo con un codice più breve e più semplice con un dizionario ? Quale valore porta sopra il codice? –

+3

@Seb: diversi motivi: in primo luogo, la descrizione si trova accanto alla dichiarazione anziché altrove se si utilizza un dizionario. In secondo luogo, la descrizione è sempre presente con il tipo enum, che porta a ... infine, il tipo può essere importato in un altro assembly e i valori enum e le loro descrizioni possono essere riflessi e presentati all'utente (utile per gli editor ed è di qualche tipo Ho fatto). – Skizz

+0

Grazie Skizz, per avermi risparmiato il tempo;) Ben fatto. – danijels

0

Utilizzo di enum in non anti-pattern. In alcuni libri sul refactoring questo codice è usato per dimostrare come sostituirlo con il polimorfismo. Sarebbe OK quando usi eccessivamente le enumerazioni nel codice.

+1

Non è stato quello che è stato detto. Ho chiesto degli anti-pattern che coinvolgano le enumerazioni. –

1

Questa non è una risposta, oltre a contribuire a un elenco di anti-pattern Enum.

Durante una revisione del codice questa mattina, mi sono imbattuto in un caso simile al seguente, tutti nella stessa classe.

due casi:

  1. prima di bere
  2. Dopo aver bevuto

..

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


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