Stavo scrivendo questo codice:
private static Expression<Func<Binding, bool>> ToExpression(BindingCriterion criterion)
{
switch (criterion.ChangeAction)
{
case BindingType.Inherited:
var action = (byte)ChangeAction.Inherit;
return (x => x.Action == action);
case BindingType.ExplicitValue:
var action = (byte)ChangeAction.SetValue;
return (x => x.Action == action);
default:
// TODO: Localize errors
throw new InvalidOperationException("Invalid criterion.");
}
}
Ed è stato sorpreso di trovare un errore di compilazione:
Una variabile locale denominata "azione" è già definita in questo ambito
È stato un problema abbastanza semplice da risolvere; solo sbarazzarsi del secondo ha varfatto il trucco.
Evidentemente le variabili dichiarate in caseblocchi hanno lo scopo del genitore switch, ma sono curioso di sapere perché. Dato che C # non consente l'esecuzione cadere attraverso altri casi (che richiede break , return, throwo goto caseistruzioni alla fine di ogni caseblocco), sembra abbastanza strano che consentirebbe dichiarazioni di variabili all'interno di uno caseda utilizzare o conflitto con le variabili in qualsiasi altra case. In altre parole, le variabili sembrano cadere nelle caseistruzioni anche se l'esecuzione non può. C # fa di tutto per promuovere la leggibilità vietando alcuni costrutti di altre lingue che sono confusi o o facilmente abusabili. Ma sembra che sia solo destinato a creare confusione. Considera i seguenti scenari:
Se dovessi cambiarlo in questo:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);Ottengo " Utilizzo della variabile locale non assegnata 'action' ". Questo è confuso perché in ogni altro costrutto in C # che mi viene in mente
var action = ...si inizializzerebbe la variabile, ma qui la dichiara semplicemente.Se dovessi scambiare i casi in questo modo:
case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; return (x => x.Action == action); case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action);Ottengo " Impossibile utilizzare la variabile locale 'action' prima che venga dichiarata ". Quindi l'ordine dei case case sembra essere importante qui in un modo che non è del tutto ovvio - normalmente potrei scriverli nell'ordine che desidero, ma poiché il
varmust deve apparire nel primo blocco doveactionviene usato, devo modificare icaseblocchi di conseguenza.Se dovessi cambiarlo in questo:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;Quindi non ricevo alcun errore, ma in un certo senso sembra che alla variabile venga assegnato un valore prima che venga dichiarato.
(Anche se non riesco a pensare a quando vorresti davvero farlo, non sapevo nemmeno chegoto caseesistesse prima di oggi)
Quindi la mia domanda è: perché i progettisti di C # non hanno dato ai caseblocchi il loro ambito locale? Ci sono ragioni storiche o tecniche per questo?
switchaffatto - Sono solo curioso di sapere il ragionamento alla base di questo disegno.
breaknon sia possibile in C #.
actionvariabile primaswitchdell'istruzione o metti ogni caso tra parentesi graffe e otterrai un comportamento ragionevole.