Co powoduje ten problem?
Wydaje mi się, że to błąd kompilatora. A przynajmniej tak. Chociaż wyrażenia decimal.TryParse(v, out a)i decimal.TryParse(v, out b)są obliczane dynamicznie, spodziewałem się, że kompilator nadal zrozumie, że zanim dotrze a <= b, oba ai bzostaną ostatecznie przypisane. Nawet z dziwactwami, które możesz wymyślić podczas dynamicznego pisania, spodziewałbym się, że kiedykolwiek ocenię tylko a <= bpo ocenie obu TryParsewywołań.
Jednak okazuje się, że za pośrednictwem operatora i nawrócenia trudne, jest to całkowicie możliwe, aby mieć wyraz A && B && Cktóra ocenia Ai C, ale nie B- Jeśli jesteś przebiegły dość. Zobacz raport o błędzie Roslyn, aby zapoznać się z genialnym przykładem Neala Gaftera.
Wykonanie tej pracy dynamicjest jeszcze trudniejsze - semantyka stosowana, gdy operandy są dynamiczne, jest trudniejsza do opisania, ponieważ aby wykonać rozwiązanie przeciążenia, musisz ocenić operandy, aby dowiedzieć się, jakie typy są zaangażowane, co może być sprzeczne z intuicją. Jednak ponownie Neal wymyślił przykład, który pokazuje, że błąd kompilatora jest wymagany ... to nie jest błąd, to naprawa błędu . Ogromne uznanie dla Neala za udowodnienie tego.
Czy można to naprawić poprzez ustawienia kompilatora?
Nie, ale istnieją alternatywy, które pozwalają uniknąć błędu.
Po pierwsze, możesz zatrzymać dynamikę - jeśli wiesz, że będziesz używać tylko łańcuchów, możesz użyć IEnumerable<string> lub nadać zmiennej zakresu vtyp string(tj from string v in array.). To byłaby moja preferowana opcja.
Jeśli naprawdę chcesz zachować dynamikę, po prostu podaj bwartość na początek:
decimal a, b = 0m;
To nie zaszkodzi - wiemy, że tak naprawdę twoja dynamiczna ocena nie zrobi nic szalonego, więc nadal będziesz przypisywać wartość bprzed jej użyciem, sprawiając, że początkowa wartość będzie nieistotna.
Dodatkowo wydaje się, że dodawanie nawiasów też działa:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
To zmienia punkt, w którym wyzwalane są różne elementy rozwiązania przeciążenia, i sprawia, że kompilator jest zadowolony.
Pozostaje jeszcze jedna kwestia - zasady specyfikacji dotyczące określonego przypisania do &&operatora muszą zostać wyjaśnione, aby stwierdzić, że mają one zastosowanie tylko wtedy, gdy &&operator jest używany w jego „zwykłej” implementacji z dwoma booloperandami. Spróbuję się upewnić, że zostanie to naprawione dla następnego standardu ECMA.
bpo przypisaniu go za pomocąoutparametru.