Я прочитал спецификацию языка 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.
Но оценка xxof не 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?имеет значения. (Конечно, это не полный ответ, а только его зародыш.)