Przeczytałem specyfikację języka C # dotyczącą warunkowych operatorów logicznych || i &&, znanych również jako zwierające operatory logiczne. Wydawało mi się niejasne, czy istniały one dla wartości logicznych dopuszczających wartość null, tj. Typu operandu Nullable<bool>(również napisanego bool?), więc wypróbowałem to z typowaniem niedynamicznym:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
To wydawało się rozstrzygać kwestię (nie mogłem jasno zrozumieć specyfikacji, ale zakładając, że implementacja kompilatora Visual C # była poprawna, teraz wiedziałem).
Jednak chciałem też spróbować z dynamicwiązaniem. Więc zamiast tego spróbowałem:
static class Program
{
static dynamic A
{
get
{
Console.WriteLine("'A' evaluated");
return true;
}
}
static dynamic B
{
get
{
Console.WriteLine("'B' evaluated");
return null;
}
}
static void Main()
{
dynamic x = A | B;
Console.WriteLine((object)x);
dynamic y = A & B;
Console.WriteLine((object)y);
dynamic xx = A || B;
Console.WriteLine((object)xx);
dynamic yy = A && B;
Console.WriteLine((object)yy);
}
}
Zaskakującym wynikiem jest to, że działa to bez wyjątku.
Cóż, xi ynie jest to zaskakujące, ich deklaracje prowadzą do pobrania obu właściwości, a wynikowe wartości są zgodne z oczekiwaniami, xjest truei yjest null.
Ale ewaluacja xxz A || Bołowiu do wiązania bez wyjątku czasu, a tylko nieruchomość Azostała przeczytana, nie B. Dlaczego to się dzieje? Jak widać, moglibyśmy zmienić Bmetodę pobierającą, aby zwracała szalony obiekt, taki jak "Hello world"i xxnadal oceniałby truebez problemów z wiązaniem ...
Ocenianie A && B(dla yy) również nie prowadzi do błędu w czasie wiązania. I tutaj oczywiście pobierane są obie właściwości. Dlaczego jest to dozwolone przez spinacz czasu wykonywania? Jeśli zwracany obiekt z Bzostanie zmieniony na „zły” obiekt (taki jak a string), występuje wyjątek wiązania.
Czy to prawidłowe zachowanie? (Jak możesz to wywnioskować ze specyfikacji?)
Jeśli spróbujesz Bjako pierwszy operand, oba B || Ai B && Adaj wyjątek spinacza czasu wykonywania ( B | Ai B & Adziała dobrze, ponieważ wszystko jest normalne z operatorami nie powodującymi zwarcia |i &).
(Wypróbowano z kompilatorem C # programu Visual Studio 2013 i wersją środowiska wykonawczego .NET 4.5.2).
Nullable<Boolean>zaangażowania, tylko wartości logiczne w pudełku są traktowane jakodynamic- Twój test zbool?jest nieistotny. (Oczywiście nie jest to pełna odpowiedź, tylko zalążek jednego.)