Ich habe diesen Code geschrieben:
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.");
}
}
Und war überrascht, einen Kompilierungsfehler zu finden:
In diesem Bereich ist bereits eine lokale Variable mit dem Namen 'action' definiert
Es war ein ziemlich leicht zu lösendes Problem. Nur den zweiten loszuwerden, war var
der Trick.
In case
Blöcken deklarierte Variablen haben offensichtlich den Gültigkeitsbereich des übergeordneten Elements switch
, aber ich bin gespannt, warum dies so ist. Da C # nicht Ausführung ermöglichen , durch andere Fälle zu fallen (es erfordert break
, return
, throw
, oder goto case
Aussagen am Ende eines jeden case
Blocks), so scheint es ziemlich merkwürdig , dass es Variablendeklarationen erlauben würde , innerhalb eines case
zu verwendenden oder Konflikt mit Variablen in jedem anderen case
. Mit anderen Worten, Variablen scheinen durch case
Anweisungen zu fallen , obwohl dies bei der Ausführung nicht möglich ist. C # ist sehr bemüht, die Lesbarkeit zu fördern, indem es einige Konstrukte anderer Sprachen verbietet, die verwirrend sind oder leicht missbraucht werden. Aber das scheint nur Verwirrung zu stiften. Stellen Sie sich die folgenden Szenarien vor:
Wenn es so geändert werden soll:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);
Ich erhalte die Meldung " Verwendung der nicht zugewiesenen lokalen Variablen 'action' ". Dies ist verwirrend, weil in jedem anderen Konstrukt in C #, das mir
var action = ...
einfällt, die Variable initialisiert wird, aber hier wird sie einfach deklariert.Wenn ich die Fälle so vertauschen würde:
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);
Ich erhalte die Meldung "Die lokale Variable 'action' kann nicht verwendet werden, bevor sie deklariert wurde ". Die Reihenfolge der Case-Blöcke scheint hier also in einer Weise wichtig zu sein, die nicht ganz offensichtlich ist. Normalerweise könnte ich diese in einer beliebigen Reihenfolge schreiben, aber da die
var
im ersten Block erscheinen müssen, in dem sieaction
verwendet werden, muss ich diecase
Blöcke anpassen entsprechend.Wenn es so geändert werden soll:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;
Dann erhalte ich keine Fehlermeldung, aber in gewissem Sinne sieht es so aus, als würde der Variablen ein Wert zugewiesen, bevor sie deklariert wird.
(Obwohl mir keine Zeit einfällt, zu der Sie das tatsächlich tun möchten - ich wusste nicht einmal, dassgoto case
es das schon heute gab)
Meine Frage ist also, warum haben die Designer von C # den case
Blöcken nicht ihren eigenen lokalen Geltungsbereich gegeben? Gibt es dafür historische oder technische Gründe?
switch
zu verwenden. Ich bin nur neugierig auf die Gründe für dieses Design.
break
, in C # nicht möglich ist.
action
Variable vor derswitch
Anweisung, oder setzen Sie jeden Fall in eine eigene Klammer, und Sie erhalten ein vernünftiges Verhalten.