注意
本文是特性规范。 此规范是功能的设计文档。 它包括建议的规范变更,以及功能设计和开发过程中所需的信息。 这些文章将持续发布,直至建议的规范变更最终确定并纳入当前的 ECMA 规范。
功能规范与已完成的实现之间可能存在一些差异。 这些差异记录在相关的语言设计会议 (LDM) 说明中。
可以在有关规范的文章中了解更多有关将功能规范子块纳入 C# 语言标准的过程。
支持者问题:https://github.com/dotnet/csharplang/issues/2460
条件表达式转换
对于条件表达式 c ? e1 : e2,当
- 没有适合
e1和e2的常见类型,或者 - 存在一个常见类型,但表达式
e1或e2中的一个没有隐式转换为该类型
我们定义了一个新的隐式条件表达式转换,它允许从条件表达式隐式转换为任何类型 T,其中存在从 e1 到 T 以及从 e2 到 T 的表达式转换。 如果一个条件表达式既没有 e1 和 e2 之间的公共类型,也没有经过条件表达式转换,则这是一个错误。
更好的从表达式转换
我们更改
更好的从表达式转换
给定从表达式
C1转换为类型E的隐式转换T1,以及从表达式C2转换为类型E的隐式转换T2,当C1不与 完全匹配时, 是一个比C2更好的E,并且至少满足以下条件之一:
接收方
更好的从表达式转换
给定从表达式
C1转换为类型E的隐式转换T1,以及从表达式C2转换为类型E的隐式转换T2,当C1不与 完全匹配时, 是一个比C2更好的E,并且至少满足以下条件之一:
Cast 表达式
当前的 C# 语言规范指出
形式为 的
(T)E会将T的值显式转换 (§10.3) 为类型E,其中 是一个类型,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 是 转换目标)。 此重大更改似乎不那么严重,因为它不会以无提示方式更改现有程序的行为。
在强制转换表达式上添加注释的原因是为了处理这样的情况:
_ = (short)(b ? 1 : 2);
此程序当前使用从 int 到 short的显式转换,我们希望保留此程序的当前语言含义。 更改在运行时是无法观察到的,但使用以下程序,可以观察到更改:
_ = (A)(b ? c : d);
其中,c 的类型为 C,d 的类型为 D,并且存在从 C 到 D 的隐式用户定义转换,以及从 D 到 A 的隐式用户定义转换,以及从 C 到 A 的隐式用户定义转换。 如果这段代码是在 C# 9.0 之前编译的,则当 b 为 true 时,我们将从 c 转换为 D,然后转换为 A。 如果使用条件表达式转换,则当 b 为 true 时,我们将直接从 c 转换为 A,这将执行不同的用户代码序列。 因此,我们将条件表达式转换视为强制转换中的最后手段,以保留现有行为。