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


Target-Typed условное выражение

Заметка

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

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

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

Преобразование условного выражения

Для условного выражения c ? e1 : e2, когда

  1. Нет общего типа для e1 и e2или
  2. для которого существует общий тип, но одно из выражений e1 или e2 не имеет неявного преобразования в этот тип

мы определяем новое неявное преобразование условного выражения , которое позволяет неявное преобразование условного выражения в любой тип T, для которого существует преобразование из выражения e1 в T, а также из e2 в T. Это ошибка, если условное выражение не имеет общего типа между e1 и e2 и не подлежит преобразованию условного выражения.

Улучшение преобразования из выражения

Мы изменяем

Лучшее преобразование из выражения

Учитывая неявное преобразование C1, которое преобразуется из выражения E в тип T1, и неявное преобразование C2, которое преобразуется из выражения E в тип T2, C1 — это лучшее преобразование, чем C2, если E точно не соответствует T2 и хотя бы одному из следующих удержаний:

  • E точно соответствует T1 (§12.6.4.5)
  • T1 является лучшей целью преобразования, чем T2 (§12.6.4.7)

Кому

Более качественное преобразование выражения

Учитывая неявное преобразование C1, которое преобразуется из выражения E в тип T1, и неявное преобразование C2, которое преобразуется из выражения E в тип T2, C1 — это лучшее преобразование, чем C2, если E точно не соответствует T2 и хотя бы одному из следующих удержаний:

  • E точно соответствует T1 (§12.6.4.5)
  • C1 не является преобразованием условного выражения, а C2преобразованием условного выражения.
  • T1 является лучшей целью преобразования, чем T2 (§12.6.4.7) , и либо C1, либо C2 представляют собой преобразования условных выражений, или ни один из них не является преобразованием условного выражения.

Выражение приведения

Текущая спецификация языка C# говорит

cast_expression формы (T)E, где T — это тип , а E — это unary_expression, выполняет явное преобразование (§10.3) значения E в тип T.

При наличии преобразования условного выражения может быть несколько возможных преобразований из E в T. При добавлении преобразования условных выражениймы предпочтём любое другое преобразование вместо преобразования условного выраженияи используем преобразование условного выражения только в крайнем случае.

Заметки по дизайну

Причина изменения в Улучшение преобразования из выражения заключается в обработке такого случая:

M(b ? 1 : 2);

void M(short);
void M(long);

Этот подход имеет два небольших недостатка. Во-первых, это не совсем так же, как выражение switch:

M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)

Это все еще критическое изменение, но его область менее вероятно повлияет на реальные программы.

M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.

M(short, short);
M(long, long);

Это становится неоднозначным, поскольку преобразование в long лучше для первого аргумента (так как оно не использует преобразование условного выражения), но преобразование в short лучше для второго аргумента (так как short является более лучшим целевым объектом преобразования, чем long). Это критическое изменение кажется менее серьезным, поскольку оно не изменяет незаметно поведение имеющейся программы.

Причина примечаний к выражению приведения состоит в обработке такого случая:

_ = (short)(b ? 1 : 2);

В настоящее время эта программа использует явное преобразование из int в short, и мы хотим сохранить текущее значение языка этой программы. Изменение будет незаметно на этапе выполнения, но в следующей программе изменение будет наблюдаться:

_ = (A)(b ? c : d);

где c имеет тип C, d имеет тип D, и существует неявное пользовательское преобразование из C в D, а неявное пользовательское преобразование из D в Aи неявное преобразование, определяемое пользователем, из C в A. Если этот код компилируется до C# 9.0, когда b является истинным, мы преобразуем из c в D, а затем в A. Если мы используем преобразование условных выражений в режиме, то при истинности b мы преобразуем из c в A напрямую, что приводит к выполнению другой последовательности пользовательского кода. Поэтому мы трактуем преобразование условных выражений как крайнюю меру приведения, чтобы сохранить существующее поведение.