Ich habe die C # -Sprachenspezifikation für die bedingten logischen Operatoren gelesen ||und &&auch als kurzschließende logische Operatoren bezeichnet. Für mich schien es unklar, ob diese für nullfähige Boolesche Werte existieren, dh für den Operandentyp Nullable<bool>(ebenfalls geschrieben bool?), also habe ich es mit nicht dynamischer Typisierung versucht:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
Das schien die Frage zu klären (ich konnte die Spezifikation nicht klar verstehen, aber vorausgesetzt, die Implementierung des Visual C # -Compilers war korrekt, jetzt wusste ich es).
Ich wollte es aber auch mit dynamicBindung versuchen . Also habe ich stattdessen versucht:
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);
}
}
Das überraschende Ergebnis ist, dass dies ausnahmslos läuft.
Nun, xund yes ist nicht überraschend, dass ihre Deklarationen dazu führen, dass beide Eigenschaften abgerufen werden und die resultierenden Werte wie erwartet sind, xsind trueund ysind null.
Aber die Auswertung für xxvon A || BBlei zu keiner Bindung einmaligen Ausnahme und nur die Eigenschaft Agelesen wurden, nicht B. Warum passiert das? Wie Sie sehen können, könnten wir den BGetter so ändern , dass er ein verrücktes Objekt zurückgibt "Hello world", und xxwürden es trotzdem trueohne Bindungsprobleme auswerten ...
Das Auswerten A && B(für yy) führt auch zu keinem Bindungszeitfehler. Und hier werden natürlich beide Eigenschaften abgerufen. Warum ist dies durch den Laufzeitbinder zulässig? Wenn das zurückgegebene Objekt von Bin ein "fehlerhaftes" Objekt (wie a string) geändert wird , tritt eine verbindliche Ausnahme auf.
Ist das richtig? (Wie können Sie das aus der Spezifikation ableiten?)
Wenn Sie es Bals ersten Operanden versuchen , geben Sie beide aus B || Aund B && Ageben eine Laufzeitbinder-Ausnahme aus ( B | Aund B & Afunktionieren einwandfrei, da bei nicht kurzgeschlossenen Operatoren |und normal alles normal ist &).
(Versucht mit dem C # -Compiler von Visual Studio 2013 und der Laufzeitversion .NET 4.5.2.)
Nullable<Boolean>Beteiligung, nur Boxed Booleans, die als behandelt werdendynamic- Ihr Test mitbool?ist irrelevant. (Natürlich ist dies keine vollständige Antwort, nur der Keim von einem.)