У короткозамкнутых операторов || и && существуют для булевых значений, допускающих нулевое значение? RuntimeBinder иногда так думает

Я прочитал спецификацию языка 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.

Но оценка дляxx изA || B не приводить к исключению времени привязки, а только к свойствуA был прочитан, а неB, Почему это происходит? Как вы можете сказать, мы могли бы изменитьB добытчик, чтобы вернуть сумасшедший объект, как"Hello world", а такжеxx все равно оценитеtrue без проблем связывания ...

ОценкаA && B (заyy) также не приводит к ошибке времени привязки. И здесь оба свойства извлекаются, конечно. Почему это разрешено связующим во время выполнения? Если возвращенный объект изB изменяется на «плохой» объект (например,string), возникает обязательное исключение.

Это правильное поведение? (Как вы можете вывести это из спецификации?)

Если вы попытаетесьB как первый операнд, обаB || A а такжеB && A дать исключение связующего во время выполнения (B | A а такжеB & A работает нормально, так как все нормально с операторами без короткого замыкания| а также&).

(Пробовал с C # компилятором Visual Studio 2013 и рабочей версией .NET 4.5.2.)

Ответы на вопрос(3)

Ваш ответ на вопрос