Я прочитал спецификацию языка С# для условных логических операторов ||
и &&
, также известных как короткие замыкающие логические операторы. Мне показалось неясным, существуют ли они для нулевых булевых элементов, то есть типа операнда Nullable<bool>
(также написано bool?
), поэтому я попробовал его с нединамической типизацией:
bool a = true;
bool? b = null;
bool? xxxx = b || a; // compile-time error, || can't be applied to these types
Казалось, что он решил вопрос (я не мог четко понять спецификацию, но предполагая, что реализация компилятора Visual С# была правильной, теперь я знал).
Однако, я хотел попробовать с привязкой 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
.
Но оценка для xx
of A || B
приводит к отсутствию исключения времени привязки, и было прочитано только свойство A
, а не B
. Почему это происходит? Как вы можете сказать, мы могли бы изменить геттер B
, чтобы вернуть сумасшедший объект, например "Hello world"
, и xx
все равно оценили бы до true
без проблем привязки...
Оценка A && B
(для yy
) также приводит к ошибке привязки-времени. И здесь оба свойства извлекаются, конечно. Почему это разрешено связующим ведром? Если возвращаемый объект из B
изменен на "плохой" объект (например, string
), произойдет исключение связывания.
Это правильное поведение? (Как вы можете сделать вывод, что из спецификации?)
Если вы попробуете B
в качестве первого операнда, то как B || A
, так и B && A
выдают исключение связывания во время выполнения (B | A
и B & A
работают нормально, поскольку все нормально с операторами без короткого замыкания |
и &
).
(Пробовался с компилятором С# Visual Studio 2013 и версией .NET.NET 4.5.2.)