我读了关于 条件逻辑运算符||
和 &&
的 C # 语言规范,也就是众所周知的短路逻辑运算符。对我来说,似乎不清楚这些是否存在可空布尔值,即操作数类型 Nullable<bool>
(也写成了 bool?
) ,所以我尝试使用非动态类型:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
这似乎解决了问题(我不能清楚地理解规范,但假设 Visual C # 编译器的实现是正确的,现在我知道了)。
但是,我也想尝试 dynamic
绑定,所以我尝试了以下方法:
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);
}
}
令人惊讶的结果是,这种方法无一例外地运行。
好吧,x
和 y
并不令人惊讶,它们的声明导致两个属性都被检索,并且结果值如预期的那样,x
是 true
,y
是 null
。
但是对 A || B
的 xx
的计算没有导致绑定时异常,只读取了属性 A
,而没有读取属性 B
。为什么会这样?正如您可以看到的,我们可以更改 B
getter 以返回一个疯狂的对象,比如 "Hello world"
,而且 xx
仍然可以计算到 true
而不会出现绑定问题..。
评估 A && B
(对于 yy
)也不会导致绑定时间错误。当然,这里两个属性都被检索到。为什么运行时活页夹允许这样做?如果从 B
返回的对象更改为“坏”对象(如 string
) ,则会发生绑定异常。
这是正确的行为吗? (您如何从规范中推断出这一点?)
如果您尝试将 B
作为第一个操作数,那么 B || A
和 B && A
都会给出运行时绑定器异常(B | A
和 B & A
工作得很好,因为非短路操作符 |
和 &
一切正常)。
(使用 Visual Studio 2013的 C # 编译器和运行时版本.NET 4.5.2进行了尝试。)