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 var
fait l'affaire.
Il est évident que les variables déclarées dans des case
blocs 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
, throw
ou des goto case
déclarations à la fin de chaque case
bloc), 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 case
instructions, 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
var
doit apparaître dans le premier bloc oùaction
est utilisé, je dois modifier descase
blocs 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 case
existait avant aujourd'hui)
Ma question est donc la suivante: pourquoi les concepteurs de C # n’ont-ils pas donné aux case
blocs leur propre portée locale? Y a-t-il des raisons historiques ou techniques à cela?
switch
du tout - je suis simplement curieux de connaître le raisonnement derrière cette conception.
break
n'est pas possible en C #.
action
variable avant l'switch
instruction ou mettez chaque cas entre ses accolades pour obtenir un comportement judicieux.