Поделиться через


Назначение объединения null

Заметка

Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Она включает предлагаемые изменения спецификации, а также информацию, необходимую во время проектирования и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.

Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия отражены в соответствующих заметках собрания по проектированию языка (LDM).

Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .

Сводка

Упрощает распространенный шаблон кодирования, в котором переменная назначается значением, если оно равно NULL.

В рамках этого предложения мы также снимем ограничения типа в ??, чтобы разрешить использование выражений с неограниченным типовым параметром на левой стороне.

Мотивация

Код в такой форме часто встречается.

if (variable == null)
{
    variable = expression;
}

Это предложение добавляет в язык неперегружаемый двоичный оператор, который выполняет эту функцию.

Для этой функции было по крайней мере восемь отдельных запросов сообщества.

Подробный дизайн

Мы добавим новую форму оператора присваивания

assignment_operator
    : '??='
    ;

Следует существующим семантическим правилам для составных операторов присваивания (§12.21.4), за исключением того, что мы пропускаем присваивание, если левая сторона не равна null. Ниже приведены правила для этой функции.

Учитывая a ??= b, где A является типом a, B является типом b, и A0 является базовым типом A, если A является типом значения, допускающего значение NULL:

  1. Если A не существует или является типом значения, не допускающего значение NULL, возникает ошибка во время компиляции.
  2. Если B не может быть неявно преобразован в A или A0 (если A0 существует), возникает ошибка компиляции.
  3. Если A0 существует и B неявно преобразуется в A0, а B не является динамическим, то тип a ??= bA0. a ??= b оценивается во время выполнения следующим образом:
    var tmp = a.GetValueOrDefault();
    if (!a.HasValue) { tmp = b; a = tmp; }
    tmp
    
    За исключением того, что a оценивается только один раз.
  4. В противном случае тип a ??= b является A. a ??= b оценивается в среде выполнения как a ?? (a = b), за исключением того, что a оценивается только один раз.

Для снижения жесткости требований типа ??мы вносим изменения в спецификацию, в которой сейчас указано, что при условии a ?? b, где A является типом a:

  1. Если A существует и не является типом, допускаемым значением NULL или ссылочным типом, возникает ошибка во время компиляции.

Мы ослабляем это требование:

  1. Если A существует и является типом значения, не допускающего значение NULL, возникает ошибка во время компиляции.

Это позволяет оператору объединения null работать с параметрами без ограничений типа, так как параметр без ограничений типа T существует, не является типом, допускающим значение NULL, и не является ссылочным типом.

Недостатки

Как и с любой языковой функцией, мы должны задаться вопросом, оправдана ли дополнительная сложность языка дополнительной ясностью, предлагаемой совокупности программ на C#, которые выигрывают от использования этой функции.

Альтернативы

Программист может писать (x = x ?? y), if (x == null) x = y;или x ?? (x = y) вручную.

Неразрешенные вопросы

  • [ ] Следует ли также поддерживать операторы &&= и ||=?

Собрания по дизайну

Никакой.