共用方式為


目標類型 new 表達式

注意

本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。

功能規格與已完成實作之間可能有一些差異。 這些差異是在 的相關語言設計會議(LDM)注意事項中擷取的。

您可以在規格的文章中,深入了解將功能規範提案納入C#語言標準的過程

冠軍問題: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,若 TSystem.Nullable的實例,則類型 T0T的基礎類型。 否則 T0T。 轉換為類型 Ttarget_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 會產生新的破壞性變更類別存在一些疑慮,但我們已經有 nulldefault,這並不是一個重大問題。

替代方案

大部分關於類型在欄位初始化中太長而無法重複的抱怨是 類型自變數, 不是類型本身,我們只能從自變數或集合初始化表達式本機推斷類型自變數,例如 new Dictionary(...)(或類似的)和推斷類型自變數。

問題

  • 我們應該禁止表達式樹狀結構中的使用方式嗎? (否)
  • 功能如何與 dynamic 自變數互動? (無特殊待遇)
  • IntelliSense 應該如何使用 new()? (只有在有單一目標類型時)

設計會議