目標類型
注意
本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。
功能規格與已完成實作之間可能有一些差異。 這些差異是在 的相關語言設計會議(LDM)注意事項中擷取的。
冠軍問題:https://github.com/dotnet/csharplang/issues/100
總結
當類型為已知時,不需要建構函式的類型規格。
動機
允許欄位初始化,而不複製類型。
Dictionary<string, List<int>> field = new() {
{ "item1", new() { 1, 2, 3 } }
};
允許在可以從使用推斷出類型時省略類型。
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
實例化物件,而不明確指定類型。
private readonly static object s_syncObj = new();
規格
新的語法形式 target_typed_new 被接受,其中 object_creation_expression 的 類型 是選擇性的。
object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
| target_typed_new
;
target_typed_new
: 'new' '(' argument_list? ')' object_or_collection_initializer?
;
target_typed_new 表達式沒有類型。 不過,有一個新的 物件建立轉換,這是從表達式進行的隱含轉換,從 target_typed_new 到每一個類型。
假設目標類型 T
,若 T
是 System.Nullable
的實例,則類型 T0
是 T
的基礎類型。 否則 T0
為 T
。 轉換為類型 T
的 target_typed_new 表達式的意義,與指定類型為 T0
的對應 object_creation_expression 的意義相同。
如果使用 target_typed_new 做為一元運算符或二進位運算子的操作數,或者當它不受 物件建立轉換時,就會是編譯時期錯誤。
開啟問題:我們是否應該允許委派和元組作為目標類型?
上述規則包括委派(引用類型)和元組(結構類型)。 雖然這兩種類型都是可建構的,但如果類型是可推斷的,則可以使用匿名函式或元組字面值。
(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant
(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found
雜項
以下是規格的結果:
- 允許
throw new()
(目標類型為System.Exception
) -
new
類型的目標不允許與二元運算子一起使用。 - 不允許以下情況發生當沒有目標型別時:如一元運算子,於
foreach
集合中,於using
中,於解構中,於await
表達式中,作為匿名型別屬性(new { Prop = new() }
),於lock
語句中,於sizeof
中,於fixed
語句中,於成員存取(new().field
),於動態分派作業(someDynamic.Method(new())
)中,於 LINQ 查詢中,作為is
運算子的操作數,作為??
運算子的左操作數。 - 它也不被允許作為
ref
。 - 下列類型的類型不允許作為轉換的目標
-
列舉類型:
new()
會運作(new Enum()
運作以提供預設值),但new(1)
無法運作,因為列舉類型沒有建構函式。 - 介面類型: 這與 COM 類型的對應建立表達式相同。
- 陣列類型: 陣列需要特殊的語法來提供長度。
-
動態: 我們不允許
new dynamic()
,因此不允許將dynamic
作為new()
的目標類型。 - 元組: 這些與使用基礎類型來建立物件具有相同的意思。
- object_creation_expression 中不允許的其他所有類型也排除,例如指標類型。
-
列舉類型:
缺點
針對目標型別 new
會產生新的破壞性變更類別存在一些疑慮,但我們已經有 null
和 default
,這並不是一個重大問題。
替代方案
大部分關於類型在欄位初始化中太長而無法重複的抱怨是 類型自變數, 不是類型本身,我們只能從自變數或集合初始化表達式本機推斷類型自變數,例如 new Dictionary(...)
(或類似的)和推斷類型自變數。
問題
- 我們應該禁止表達式樹狀結構中的使用方式嗎? (否)
- 功能如何與
dynamic
自變數互動? (無特殊待遇) - IntelliSense 應該如何使用
new()
? (只有在有單一目標類型時)