J'écrivais ce code:
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.");
}
}
Et a été surpris de trouver une erreur de compilation:
Une variable locale nommée 'action' est déjà définie dans cette portée
C'était un problème assez facile à résoudre; juste se débarrasser de la seconde a varfait l'affaire.
Il est évident que les variables déclarées dans des caseblocs ont la portée du parent switch, mais je suis curieux de savoir pourquoi. Étant donné que C # ne permet pas l' exécution de tomber dans d' autres cas (il exige break , return, throwou des goto casedéclarations à la fin de chaque casebloc), il semble tout à fait étrange que cela permettrait des déclarations variables à l' intérieur d' un caseà utiliser ou de conflit avec des variables dans tout autre case. En d'autres termes, les variables semblent tomber à travers les caseinstructions, même si l'exécution ne peut pas. C # prend beaucoup de peine à améliorer la lisibilité en interdisant certaines constructions de langages confus ou faciles à abuser. Mais cela semble lié à la confusion. Considérez les scénarios suivants:
Si devions le changer en ceci:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);Je reçois " Utilisation de la variable locale non affectée 'action' ". Ceci est déroutant parce que dans chaque construction en C # à laquelle je peux penser
var action = ...initialiserait la variable, mais ici, il la déclare simplement.Si je devais échanger les cas comme ceci:
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);J'obtiens " Impossible d'utiliser la variable locale 'action' avant qu'elle soit déclarée ". Donc, l'ordre des blocs de cas semble être important ici d'une manière qui n'est pas tout à fait évident - normalement je pourrais les écrire dans l'ordre que je souhaite, mais parce que le
vardoit apparaître dans le premier bloc oùactionest utilisé, je dois modifier descaseblocs en conséquence.Si devions le changer en ceci:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;Ensuite, je ne reçois aucune erreur, mais dans un sens, il semble que la variable se voit attribuer une valeur avant d'être déclarée.
(Bien que je ne puisse penser à aucun moment où vous voudriez réellement faire cela - je ne savais même pas qu'ilgoto caseexistait avant aujourd'hui)
Ma question est donc la suivante: pourquoi les concepteurs de C # n’ont-ils pas donné aux caseblocs leur propre portée locale? Y a-t-il des raisons historiques ou techniques à cela?
switchdu tout - je suis simplement curieux de connaître le raisonnement derrière cette conception.
breakn'est pas possible en C #.
actionvariable avant l'switchinstruction ou mettez chaque cas entre ses accolades pour obtenir un comportement judicieux.