Eu estava escrevendo este código:
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 ficou surpreso ao encontrar um erro de compilação:
Uma variável local denominada 'ação' já está definida neste escopo
Foi uma questão bastante fácil de resolver; apenas se livrar do segundo varfez o truque.
Evidentemente, as variáveis declaradas em caseblocos têm o escopo do pai switch, mas estou curioso para saber por que isso acontece. Dado que C # não permite a execução de cair através de outros casos (que requer break , return, throw, ou goto casedeclarações no final de cada casebloco), parece bastante estranho que permitiria declarações de variáveis dentro de um casepara ser usado ou conflito com as variáveis em qualquer outra case. Em outras palavras, as variáveis parecem passar por caseinstruções, embora a execução não possa. O C # esforça-se ao máximo para promover a legibilidade, proibindo algumas construções de outros idiomas que sejam confusas ou que sejam facilmente abusadas. Mas isso parece apenas causar confusão. Considere os seguintes cenários:
Se fosse alterá-lo para isso:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);Recebo " Uso da variável local não atribuída 'action' ". Isso é confuso, porque em qualquer outra construção em C # que eu possa pensar
var action = ...inicializaria a variável, mas aqui ela simplesmente a declara.Se eu fosse trocar os casos assim:
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);Recebo " Não é possível usar a variável local 'action' antes de ser declarada ". Portanto, a ordem dos blocos de casos parece ser importante aqui de uma maneira que não é totalmente óbvia - normalmente eu poderia escrevê-los em qualquer ordem que desejasse, mas como os
varitens devem aparecer no primeiro bloco em queactioné usado, tenho que ajustar oscaseblocos. adequadamente.Se fosse alterá-lo para isso:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;Não recebo nenhum erro, mas, em certo sentido, parece que a variável está recebendo um valor antes de ser declarada.
(Embora eu não consiga pensar em nenhum momento em que você realmente queira fazer isso - eu nem sabia quegoto caseexistia antes de hoje)
Então, minha pergunta é: por que os designers de C # não deram aos caseblocos seu próprio escopo local? Existem razões históricas ou técnicas para isso?
switch- eu só estou curioso sobre o raciocínio por trás desse design.
breaknão seja possível em C #.
actionvariável antes daswitchdeclaração ou coloque cada caso em seu próprio aparelho, e você obterá um comportamento sensato.