Target-Typed 條件表達式
注意
本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。
功能規格與已完成實作之間可能有一些差異。 這些差異是在的相關
條件表達式轉換
若為條件表達式 c ? e1 : e2
,則為
-
e1
和e2
沒有常見的類型, 或 - 其中一般類型存在,但其中一個表達式
e1
或e2
沒有隱含轉換成該類型
我們會定義新的隱含 條件表達式轉換,允許從條件表達式隱含轉換成任何類型 T
,其中從 e1
轉換成 T
,以及從 e2
轉換成 T
。 如果條件表達式在 e1
與 e2
之間沒有通用型別,也不受限於 條件表示式轉換,則為錯誤。
從表達式進行更好的轉換
我們變更
從表達式進行更好的轉換
假設有一個隱式轉換
C1
將表達式E
轉換成類型T1
,以及一個隱式轉換C2
將表達式E
轉換成類型T2
。如果E
不完全符合T2
,並且至少滿足以下條件之一,則C1
是比C2
更好的轉換 :
到
從表達式進行更好的轉換
假設有一個隱含轉換
C1
,將表達式E
轉換為類型T1
,還有一個隱含轉換C2
,將表達式E
轉換為類型T2
,如果E
與T2
不完全相符,並且下列條件至少有一個成立,則C1
是比C2
更好的 轉換。
轉換表達式
目前的 C# 語言規格說
形式為
(T)E
的 cast_expression,其中T
是 類型,而E
是 unary_expression,則會將E
的值明確轉換為T
類型(§10.3)。
在 條件表示式轉換 的情況下,可能會有超過一種從 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
為 true 時,我們會從 c
轉換成 D
,然後轉換成 A
。 如果我們使用 條件表達式轉換,則當 b
為 true 時,我們會直接從 c
轉換成 A
,這會執行不同的使用者程式代碼序列。 因此,我們將 條件表達式轉換 視為轉型的最後手段,以保留現有的行為。