Target-Typed условное выражение
Заметка
Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Этот документ включает предлагаемые изменения спецификации, а также информацию, необходимую во время проектирования и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.
Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия фиксируются в соответствующих собраниях по проектированию языка (LDM).
Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .
Преобразование условного выражения
Для условного выражения c ? e1 : e2
, когда
- Нет общего типа для
e1
иe2
или - для которого существует общий тип, но одно из выражений
e1
илиe2
не имеет неявного преобразования в этот тип
мы определяем новое неявное преобразование условного выражения , которое позволяет неявное преобразование условного выражения в любой тип T
, для которого существует преобразование из выражения e1
в T
, а также из e2
в T
. Это ошибка, если условное выражение не имеет общего типа между e1
и e2
и не подлежит преобразованию условного выражения.
Улучшение преобразования из выражения
Мы изменяем
Лучшее преобразование из выражения
Учитывая неявное преобразование
C1
, которое преобразуется из выраженияE
в типT1
, и неявное преобразованиеC2
, которое преобразуется из выраженияE
в типT2
,C1
— это лучшее преобразование, чемC2
, еслиE
точно не соответствуетT2
и хотя бы одному из следующих удержаний:
Кому
Более качественное преобразование выражения
Учитывая неявное преобразование
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
напрямую, что приводит к выполнению другой последовательности пользовательского кода. Поэтому мы трактуем преобразование условных выражений как крайнюю меру приведения, чтобы сохранить существующее поведение.
C# feature specifications