O que causa esse problema?
Parece um bug do compilador para mim. Pelo menos, sim. Embora as expressões decimal.TryParse(v, out a)
e decimal.TryParse(v, out b)
sejam avaliadas dinamicamente, eu esperava que o compilador ainda entendesse que, no momento em que atinge a <= b
, ambos a
e b
estão definitivamente atribuídos. Mesmo com as estranhezas que você pode descobrir na digitação dinâmica, eu esperaria apenas avaliar a <= b
depois de avaliar ambas as TryParse
chamadas.
No entanto, verifica-se que por meio de operador e conversão complicada, é inteiramente viável ter uma expressão A && B && C
que avalia A
e C
mas não B
- se você for astuto o suficiente. Veja o relatório de bug de Roslyn para ver o exemplo engenhoso de Neal Gafter.
Fazer isso funcionar dynamic
é ainda mais difícil - a semântica envolvida quando os operandos são dinâmicos são mais difíceis de descrever, porque para realizar a resolução de sobrecarga, você precisa avaliar operandos para descobrir quais tipos estão envolvidos, o que pode ser contra-intuitivo. No entanto, novamente Neal veio com um exemplo que mostra que o erro do compilador é necessário ... isso não é um bug, é uma correção de bug . Muitos elogios a Neal por provar isso.
É possível consertá-lo por meio das configurações do compilador?
Não, mas existem alternativas que evitam o erro.
Em primeiro lugar, você pode impedir que seja dinâmico - se você sabe que só usará strings, pode usar IEnumerable<string>
ou dar à variável de intervalo v
um tipo de string
(ou seja from string v in array
). Essa seria minha opção preferida.
Se você realmente precisa mantê-lo dinâmico, basta fornecer b
um valor para começar:
decimal a, b = 0m;
Isso não fará mal nenhum - sabemos que na verdade sua avaliação dinâmica não fará nada maluco, então você ainda acabará atribuindo um valor a b
antes de usá-lo, tornando o valor inicial irrelevante.
Além disso, parece que adicionar parênteses também funciona:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Isso muda o ponto em que várias peças de resolução de sobrecarga são acionadas e deixa o compilador feliz.
Ainda existe um problema - as regras da especificação sobre atribuição definitiva com o &&
operador precisam ser esclarecidas para afirmar que elas só se aplicam quando o &&
operador está sendo usado em sua implementação "regular" com dois bool
operandos. Vou tentar garantir que isso seja corrigido para o próximo padrão ECMA.
b
depois de atribuí-lo por meio de umout
parâmetro.