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
caseinizializzare 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 modificareactionblocchi 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 esistessecaseprima 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?