2013-08-20 16 views
13

ho dizionario azione definita come:Utilizzando operatore ternario: "solo l'assegnazione, chiamata, incremento ..."

var actions = new Dictionary<string, Action<string, string>>(); 

ho messo lì azioni come:

actions.Add("default", (value, key) => result.Compare(value, properties[key], Comparers.SomeComparer, key)); 
... 

Sto usando questo codice per eseguirlo:

if (actions.ContainsKey(pair.Key)) 
{ 
    actions[pair.Key](pair.Value, pair.Key); 
} 
else 
{ 
    actions[""](pair.Value, pair.Key); 
} 

funziona bene, ma ho voluto usare '?' notazione per renderlo più breve:

actions.ContainsKey(pair.Key) ? actions[pair.Key](pair.Value, pair.Key) : actions[""](pair.Value, pair.Key); 

Questo codice mi mostra errore:

Error 1 Only assignment, call, increment, decrement, and new object expressions can be used as a statement

actions[pair.Key](pair.Value, pair.Key)non è una chiamata? Mi manca qualcosa? È possibile usare '?' notazione con i dizionari di azione? Stavo cercando di trovare qualcosa a riguardo ma è difficile trovare qualcosa su '?' operatore e questo errore perché '?' viene ignorato da google.

+6

Il tuo non assegnare a nulla, è anche davvero più breve? – Sayse

+1

@Sayse si non lo sono, ma c'è che devo fare "assignment, call, increment, decrement ..." e sto facendo call. Preferisco questa notazione, ma il punto principale è la mia curiosità. Voglio davvero sapere, cosa c'è di sbagliato nella mia chiamata :) – wudzik

+2

'TryGetValue' .. –

risposta

20

Prova a modificare:

actions[actions.ContainsKey(pair.Key) ? pair.key : ""](pair.Value, pair.Key); 

Ciò risolverà il problema.

+2

Grazie mille, mi ha aiutato. – wudzik

+11

Penso che questo codice non dovrebbe sostituire quello originale. Solo perché è una riga di codice non è migliore. – oddparity

+4

e perché non è meglio amico mio? –

13

Il ?: Conditional operator è definito come:

The conditional operator (?:) returns one of two values depending on the value of a Boolean expression

le vostre azioni non ritorno un valore, quindi qual è il valore di ritorno di ?: destinate ad essere?

6

Se avete davvero a fare in questo modo, si potrebbe provare

actions[actions.ContainsKey(pair.Key) ? pair.Key : ""](pair.Value, pair.Key); 

Giusto per chiarire, da : Operator (C# Reference)

The condition must evaluate to true or false. If condition is true, first_expression is evaluated and becomes the result. If condition is false, second_expression is evaluated and becomes the result. Only one of the two expressions is evaluated.

questo è equivelant

int input = Convert.ToInt32(Console.ReadLine()); 
string classify; 

// if-else construction. 
if (input < 0) 
    classify = "negative"; 
else 
    classify = "positive"; 

// ?: conditional operator. 
classify = (input < 0) ? "negative" : "positive"; 
+0

Grazie Adriaan la tua spiegazione == ottimo. – cyclical

1

ogni "? : "la dichiarazione deve essere assegnata a qualcosa, ovvero

actions.ContainsKey(pair.Key) ? actions[pair.Key](pair.Value, pair.Key) : actions[""](pair.Value, pair.Key); 

non è legale perché non assegna nulla.

si può fare:

object x = actions.ContainsKey(pair.Key) ? actions[pair.Key](pair.Value, pair.Key) : actions[""](pair.Value, pair.Key); 

e che sarebbe legale se actions[pair.Key](pair.Value, pair.Key) e actions[""](pair.Value, pair.Key); restituire un valore

+0

più preciso: ogni espressione ternaria deve restituire qualcosa – oddparity

5

Non c'è niente di sbagliato con la vostra chiamata, di per sé. L'espressione actions[pair.Key](pair.Value, pair.Key) è effettivamente una chiamata. Questa non è l'espressione di cui si lamenta il compilatore, però. Il compilatore fa riferimento all'intera espressione operatore-condizionale, che non è né un'assegnazione, una chiamata, un incremento, un decremento, né una nuova espressione oggetto, e quindi non può essere una dichiarazione da sola.

alternative includono quanto segue:

  • Assegnazione del risultato dell'espressione a un'altra variabile, rendendo il condizionale semplicemente una sotto-espressione della grande assegnamento
  • fattorizzazione condizionale nell'espressione di indice, così la dichiarazione generale è una singola chiamata piuttosto che due chiamate separate.
  • Utilizzando due affermazioni indipendenti per decidere quale chiave da utilizzare e quindi chiamare la funzione:

    var key = actions.ContainsKey(pair.Key) ? pair.Key : ""; 
    actions[key](pair.Value, pair.Key); 
    

    Evita ancora la duplicazione di codice, ma mantiene le cose più facilmente leggibile da non cercando di impacchettare tutto in una dichiarazione complessa.