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 var
fatto il trucco.
Evidentemente le variabili dichiarate in case
blocchi 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
, throw
o goto case
istruzioni alla fine di ogni case
blocco), sembra abbastanza strano che consentirebbe dichiarazioni di variabili all'interno di uno case
da utilizzare o conflitto con le variabili in qualsiasi altra case
. In altre parole, le variabili sembrano cadere nelle case
istruzioni 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
var
must deve apparire nel primo blocco doveaction
viene usato, devo modificare icase
blocchi 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 case
esistesse prima di oggi)
Quindi la mia domanda è: perché i progettisti di C # non hanno dato ai case
blocchi il loro ambito locale? Ci sono ragioni storiche o tecniche per questo?
switch
affatto - Sono solo curioso di sapere il ragionamento alla base di questo disegno.
break
non sia possibile in C #.
action
variabile primaswitch
dell'istruzione o metti ogni caso tra parentesi graffe e otterrai un comportamento ragionevole.