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.");
}
}
E sono rimasto sorpreso nel trovare un errore di compilazione:
A local variable named 'action' is already defined in this scope
È stato un problema abbastanza facile da risolvere; solo eliminare il secondo var
ha fatto il trucco.
Evidentemente le variabili dichiarate in case
blocchi hanno lo scopo del genitore switch
, ma sono curioso di sapere perché è così. Dato che C # non consente l'esecuzione di altri casi (è richiede break
, return
, throw
, o goto case
istruzioni alla fine di ogni blocco case
), sembra piuttosto strano che possa consentire l'uso di dichiarazioni variabili all'interno di un case
o di conflitto con variabili in qualsiasi altro %codice%. In altre parole, le variabili sembrano cadere attraverso case
dichiarazioni anche se l'esecuzione non può. C # si impegna a promuovere la leggibilità vietando alcuni costrutti di altre lingue che sono confusi o facilmente abusabili. Ma sembra che sia destinato a causare 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);
Ricevo " Uso della variabile locale non assegnata 'azione' ". Questo è fonte di confusione perché in ogni altro costrutto in C # posso pensare a
case
inizializzare la variabile, ma qui semplicemente lo dichiara. -
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);
I get " Impossibile usare la variabile locale 'action' prima che sia dichiarata ". Quindi l'ordine dei blocchi del caso sembra essere importante qui in un modo che non è del tutto ovvio - Normalmente potrei scriverli in qualsiasi ordine che desidero, ma perché
var action = ...
deve apparire nel primo blocco dovevar
è usato , Devo modificareaction
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 ho alcun errore, ma in un certo senso, sembra come se alla variabile fosse assegnato un valore prima che fosse dichiarato.
(Anche se non riesco a pensare a nessun tempo in cui vorresti davvero farlo - non sapevo nemmeno che esistessecase
prima di oggi)
Quindi la mia domanda è: perché i progettisti di C # non hanno dato a goto case
blocchi del loro ambito locale? Ci sono motivi storici o tecnici per questo?