2009-12-22 22 views
7

Sono interessato a considerazioni di stile e prestazioni. La mia scelta è di fare una delle seguenti (mi dispiace per il povero formattazione ma l'interfaccia di questo sito non è WYSIWYG):Istruzione switch C# .NET stringa confronto vs enum confronta

One:

string value = "ALPHA"; 

switch (value.ToUpper()) 
{ 
    case "ALPHA": 
    // do somthing 
    break; 
    case "BETA": 
    // do something else 
    break; 
    default: 
    break; 
} 

Due:

public enum GreekLetters 
{ 
    UNKNOWN= 0, 
    ALPHA= 1, 
    BETA = 2, 
    etc... 

} 

string value = "Alpha"; 
GreekLetters letter = (GreekLetters)Enum.Parse(typeof(GreekLetters), value.ToUpper()); 

switch(letter) 
{ 
    case GreekLetters.ALPHA: 
     // do something 
     break; 
    case GreekLetters.BETA: 
     // do something else 
     break; 
    default: 
     break; 
} 

Personalmente, Preferisco l'opzione DUE di seguito, ma non ho alcun motivo reale se non per motivi di stile di base. Tuttavia, non sono nemmeno sicuro che ci sia davvero una ragione di stile. Grazie per il tuo contributo.

+0

Sarebbe un'ottima domanda per il colloquio - suggerirei che lo avreste sicuramente verificato con il profiling, in quanto dipenderebbe dalle prestazioni di 'Enum.Parse()' - ovviamente, opzione due sono più facili da mantenere da una prospettiva di errore, anche se le prestazioni sono paragonabili ... –

+0

+1 per contrassegnare il valore enum di 0 come "sconosciuto". –

risposta

4

L'opzione 1 è più veloce perché se si look at the code per Enum.Parse, si vedrà che passa attraverso ogni elemento uno per uno, cercando una corrispondenza. Inoltre, c'è meno codice da mantenere e mantenere costante.

Una parola di cautela è che non è necessario utilizzare ToUpper, ma piuttosto ToUpperInvariant() a causa di problemi Turkey Test.

Se si insiste sull'opzione # 2, utilizzare almeno il sovraccarico che consente di specificare di ignorare il caso. Questo sarà più veloce della conversione in maiuscolo. Inoltre, si tenga presente che lo Framework Design Guidelines incoraggia tutti i valori enum a essere PascalCase anziché SCREAMING_CAPS.

+2

Seriamente, SCREAMING_CAPS è talmente C++ –

9

La seconda opzione è leggermente più veloce, poiché la prima opzione potrebbe richiedere un confronto completo tra stringhe. Tuttavia, la differenza sarà troppo piccola per essere misurata nella maggior parte delle circostanze.

Il vero vantaggio della seconda opzione è che hai reso esplicito che i valori validi per value rientrano in un intervallo ristretto. Infatti, genererà un'eccezione a Enum.Parse se il valore di stringa non è nell'intervallo previsto, che è spesso esattamente ciò che si desidera.

+0

La seconda opzione è più lenta perché richiede un riscontro di riflessione per raccogliere tutti i campi e quindi un elemento per confronto degli articoli. Indico il codice sorgente del framework nella mia risposta per dimostrarlo. –

1

Direi sicuramente il n. Enum.Parse() causa una riflessione che è relativamente costosa. Inoltre, Enum.Parse() genererà un'eccezione se non è definita e poiché non c'è TryParse() avresti bisogno di avvolgerla nel blocco Try/Catch

2

Non posso commentare la parte relativa alle prestazioni della domanda ma per quanto riguarda lo stile preferisco l'opzione n. 2. Ogni volta che ho un insieme noto di valori e il set è ragionevolmente piccolo (meno di un paio di dozzine circa) preferisco usare un enum. Trovo che un enum sia molto più semplice da utilizzare rispetto a una raccolta di valori stringa e chiunque guardi il codice può vedere rapidamente quale sia l'insieme di valori consentiti.

0

Non sono sicuro se c'è una differenza di prestazioni quando si attiva un valore di stringa rispetto a un enum.

Una cosa da considerare è che avresti bisogno dei valori usati per le istruzioni case in altre parti del tuo codice. Se è così, allora usare enum avrebbe più senso se si ha una definizione singolare dei valori. Si potrebbero anche usare le stringhe di Const.

2

Questo in realtà dipende dal numero di elementi nell'enumerazione e sarà necessario testarlo per ogni specifico scenario, non che sia probabile che faccia una grande differenza. Ma è una grande domanda.

Con pochissimi valori, Enum.Parse richiederà più tempo di qualsiasi altro in entrambi gli esempi, quindi il secondo dovrebbe essere più lento.

Con valori sufficienti, l'istruzione switch verrà implementata come una tabella hash, che dovrebbe funzionare alla stessa velocità con stringhe ed enumerazioni, quindi, ancora una volta, Enum.Parse probabilmente renderà la seconda soluzione più lenta, ma non relativamente.

Da qualche parte nel mezzo, mi aspetto che il costo del confronto delle stringhe sia più alto rispetto al confronto delle enumerazioni renderebbe la prima soluzione più veloce.

Non sarei nemmeno sorpreso se fosse diverso su diverse versioni del compilatore o opzioni diverse.