2010-05-24 6 views
22

Sto scrivendo un parser che chiama alcune funzioni che dipendono da qualche valore.Dizionario con delegato o switch?

posso implementare questa logica di interruttore semplice come questo:

switch(some_val) 
{ 
    case 0: 
     func0(); 
     break; 
    case 1: 
     func1(); 
     break; 
}  

o per delegati e un dizionario come questo:

delegate void some_delegate(); 
Dictionary<int, some_delegate> some_dictionary = new Dictionary<int, some_delegate>(); 
some_dictionary[0] = func0; 
some_dictionary[1] = func1; 

some_dictionary[some_value].Invoke();  

Sono questi due metodi equivalenti e che è preferito?

risposta

9

In termini di accesso, sono identici: entrambi basta controllare se quel valore specifico ha un corrispondente risultato. Tuttavia, un dizionario genererà un'eccezione out-of-bounds se si tenta di accedere a una chiave inesistente.

La scelta dovrebbe essere principalmente sulla riutilizzabilità. Se si ha solo bisogno di fare questa logica di ramificazione in un punto, allora usare un caso di commutazione è probabilmente più sensato che memorizzare una variabile. Se è necessario accedervi ripetutamente in punti separati, utilizzare il dizionario per evitare di ripetere ripetutamente l'istruzione switch.

+4

Si potrebbe anche usare l'alternativa vecchia scuola alla programmazione "taglia e incolla". Metti l'istruzione switch in un metodo. –

2

Entrambi fanno lo stesso (beh, dovresti controllare se la chiave appare nel dictonary).

È solo una questione di leggibilità. Ciò che sembra il migliore per te e più importante, cosa preferirebbero le persone che leggono il tuo codice.

(penso che il dizionario)

+0

Grazie per la tua risposta. Ora che entrambi fanno lo stesso, in altri casi la domanda non avrebbe alcun significato :) –

11

preferisco fortemente la scelta dizionario, perché con un inizializzatore, può essere molto più compatto e leggibile:

var actions = new Dictionary<int, Action> 
{ 
    {1,() => Console.WriteLine("One!")}, 
    {2,() => Console.WriteLine("Two!")} 
} 

Inoltre, è necessario un po 'di flessibilità; puoi aggiungere condizioni e azioni in modo programmatico, il che è spesso utile, a seconda di cosa stai facendo.

+0

Che mi dici della velocità? –

+7

Sarà più lento dell'interruttore. Stai attento lì, però; l'ottimizzazione prematura è la radice di tutto il male. Codice per il buon design, la leggibilità e tutto il jazz, e funziona solo sulla parte di velocità se è troppo lenta per i tuoi scopi.La differenza di velocità potrebbe essere completamente trascurabile, ma le differenze di leggibilità sono reali ed evidenti. –

+0

Grazie, il tempo non è troppo critico per me in questo caso, quindi userò Dectionary con il delegato –

6

Se il tipico programmatore della tua squadra è qualcosa di simile a quelli con cui lavoro spesso, dovresti optare per l'opzione più semplice, ad esempio lo switch. I delegati mi sembrano una soluzione "intelligente" che non è necessaria.

+1

Sono d'accordo con ccomet. Se l'interruttore si verifica solo una volta nel codice, allora è l'opzione migliore, ma se viene duplicato su 2 o più metodi, il dizionario è l'approccio più pulito. I programmatori incompetenti o disinteressati rappresentano un altro problema. Non credo che sia vantaggioso scrivere il codice "minimo comune denominatore". Se la squadra non è interessata all'apprendimento, allora trova un nuovo lavoro. ;) –

+1

@Jacques Perché non semplicemente refactoring l'istruzione switch in un metodo che viene chiamato da entrambi? –

0

Se è necessario attivare stringhe in un file di risorse, ad esempio per scopi di globalizzazione, è necessario utilizzare l'approccio dizionario/delegato.

4

Mi piace l'approccio del dizionario perché ti dà la possibilità di scambiare le tue espressioni lambda in caso di necessità. Questo è un ottimo trucco per un programmatore di tenere nella loro borsa degli attrezzi per i casi che coinvolgono programmi che utilizzano alberi decisionali complessi. Sarebbe molto ingombrante modificare i blocchi del tuo switch in fase di esecuzione e la risposta migliore finirebbe per coinvolgere comunque lambda.

Una volta avevo una situazione in cui avevo bisogno di creare un'istruzione switch in modo dinamico. Questo metodo ha fornito una soluzione molto più leggibile.