Я прочитал спецификацию языка C #, посвященную условным логическим операторам ||
и &&
, также известным как логические операторы короткого замыкания. Мне казалось неясным, существуют ли они для логических значений, допускающих значение NULL, то есть типа операнда 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
.
Но оценка xx
of не A || B
привела к исключению времени привязки, и A
было прочитано только свойство , а не B
. Почему это происходит? Как вы понимаете, мы могли бы изменить метод получения, B
чтобы он возвращал сумасшедший объект, например "Hello world"
, и xx
все равно оценивал бы true
без проблем с привязкой ...
Вычисление A && B
(для yy
) также не приводит к ошибке времени привязки. И здесь, конечно, извлекаются оба свойства. Почему это разрешено связывателем времени выполнения? Если возвращенный объект из B
изменяется на «плохой» объект (например, a string
), возникает исключение привязки.
Это правильное поведение? (Как вы можете сделать это из спецификации?)
Если вы попробуете в B
качестве первого операнда, оба B || A
и B && A
выдадут исключение связующего времени выполнения ( B | A
и B & A
работают нормально, поскольку все в норме с операторами без короткого замыкания |
и &
).
(Пробовал с компилятором C # Visual Studio 2013 и версией среды выполнения .NET 4.5.2.)
Nullable<Boolean>
задействованных вообще, только логические значения в рамке, обрабатываемые какdynamic
- ваш тест с неbool?
имеет значения. (Конечно, это не полный ответ, а только его зародыш.)