Cosa causa questo problema?
A me sembra un bug del compilatore. Almeno, lo ha fatto. Sebbene le espressioni decimal.TryParse(v, out a)
e decimal.TryParse(v, out b)
vengano valutate dinamicamente, mi aspettavo che il compilatore comprendesse ancora che nel momento in cui raggiunge a <= b
, entrambe a
e b
sono state assegnate definitivamente. Anche con le stranezze che puoi trovare nella digitazione dinamica, mi aspetto di valutare solo a <= b
dopo aver valutato entrambe le TryParse
chiamate.
Tuttavia, si scopre che attraverso l'operatore e la conversione complicata, è del tutto fattibile avere un'espressione A && B && C
che valuta A
e C
ma non B
- se sei abbastanza astuto. Vedi il bug report di Roslyn per l'esempio geniale di Neal Gafter.
Fare questo lavoro dynamic
è ancora più difficile: la semantica coinvolta quando gli operandi sono dinamici è più difficile da descrivere, perché per eseguire la risoluzione del sovraccarico, è necessario valutare gli operandi per scoprire quali tipi sono coinvolti, il che può essere controintuitivo. Tuttavia, ancora una volta Neal ha escogitato un esempio che mostra che è richiesto l'errore del compilatore ... questo non è un bug, è una correzione di bug . Enormi quantità di complimenti a Neal per averlo dimostrato.
È possibile risolverlo tramite le impostazioni del compilatore?
No, ma ci sono alternative che evitano l'errore.
In primo luogo, potresti impedire che sia dinamico: se sai che utilizzerai solo stringhe, puoi usare IEnumerable<string>
o dare alla variabile di intervallo v
un tipo di string
(cioè from string v in array
). Questa sarebbe la mia opzione preferita.
Se hai davvero bisogno di mantenerlo dinamico, dai b
un valore per iniziare:
decimal a, b = 0m;
Questo non farà alcun danno: sappiamo che in realtà la tua valutazione dinamica non farà nulla di folle, quindi finirai comunque per assegnare un valore b
prima di usarlo, rendendo il valore iniziale irrilevante.
Inoltre, sembra che anche l'aggiunta di parentesi funzioni:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Ciò cambia il punto in cui vengono attivati vari pezzi di risoluzione del sovraccarico e sembra rendere felice il compilatore.
Resta ancora un problema: le regole della specifica sull'assegnazione definitiva con l' &&
operatore devono essere chiarite per affermare che si applicano solo quando l' &&
operatore viene utilizzato nella sua implementazione "regolare" con due bool
operandi. Cercherò di assicurarmi che questo sia corretto per il prossimo standard ECMA.
b
dopo averlo assegnato tramite unout
parametro.