C# 11 中的新功能

C# 11 中納入了下列功能:

.NET 7 上支援 C# 11。 如需詳細資訊,請參閱 C# 語言版本控制

您可以從 .NET 下載頁面下載最新 .NET 7 SDK。 您也可以下載 Visual Studio 2022,其包含 .NET 7 SDK。

注意

歡迎您提供這些功能的相關意見反應。 如果您發現上述這些新功能的任何功能,請在 dotnet/roslyn 存放庫中建立新問題

一般屬性

您可以宣告基類為 System.Attribute泛型類別。 此功能為需要 System.Type 參數的屬性提供更方便的語法。 先前,您必須建立採用 Type 作為其建構函式參數的屬性:

// Before C# 11:
public class TypeAttribute : Attribute
{
   public TypeAttribute(Type t) => ParamType = t;

   public Type ParamType { get; }
}

若要套用該屬性,您可以使用 typeof 運算子:

[TypeAttribute(typeof(string))]
public string Method() => default;

您可以使用這項新功能改為建立泛型屬性:

// C# 11 feature:
public class GenericAttribute<T> : Attribute { }

然後,指定使用該屬性的型別參數:

[GenericAttribute<string>()]
public string Method() => default;

套用該屬性時,您必須提供所有型別參數。 換句話說,泛型型別必須完整建構。 在上述範例中,空括弧 (()) 可以省略,因為該屬性沒有任何引數。

public class GenericType<T>
{
   [GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.
   public string Method() => default;
}

型別引數必須滿足與 typeof 運算子相同的限制。 不允許需要中繼資料批註的型別。 例如,不允許使用下列型別作為型別參數:

  • dynamic
  • string? (或任何可為 Null 的參考型別)
  • (int X, int Y) (或任何其他使用 C# 元組語法的元組類型) 。

這些型別不會直接以中繼資料表示。 包含描述型別的批註。 在所有情況下,您反而可以使用基礎型別:

  • 針對 dynamicobject
  • string 取代 string?
  • ValueTuple<int, int> 取代 (int X, int Y)

一般數學運算支援

有數種語言功能可啟用泛型數學運算支援:

  • 介面中的 static virtual 成員
  • 已檢查使用者定義的運算子
  • 寬鬆移位運算子
  • 不帶正負號的右移運算子

您可以在介面中新增 static abstractstatic virtual 成員,以定義介面中包含可多載運算子、其他靜態成員和靜態屬性的介面。 這項功能的主要案例是泛型型別中使用數學運算子。 例如,您可以在實作 operator + 的型別中實作 System.IAdditionOperators<TSelf, TOther, TResult> 介面。 其他介面會定義其他數學運算或定義完善的值。 您可以在介面一文中了解新的語法。 包含 static virtual 方法的介面通常是泛型介面。 此外,大部分都會宣告型別參數實作宣告介面的條件約束。

您可以在探索靜態抽象介面成員 (部分機器翻譯) 的教學課程中自行深入了解並嘗試此功能,或是 .NET 6 預覽功能中 - 一般數學運算 (英文) 部落格文章。

泛型數學運算在語言上建立了其他需求。

  • 不帶正負號的右移運算子:在 C# 11 之前,若要強制執行不帶正負號的右移,您必須將任何帶正負號的整數類型轉換成不帶正負號的類型、執行移位,然後將結果轉換回帶正負號的類型。 從 C# 11 開始,您可以使用 >>>不帶正負號的移位運算子
  • 寬鬆的移位運算子需求:C# 11 移除第二個運算元必須是 int 或隱含可轉換成 int 的需求。 這項變更可讓實作泛型數學運算介面的類型用於這些位置。
  • 已核取和未核取的使用者定義運算子:開發人員現在可以定義 checkedunchecked 算術運算子。 編譯器會根據目前內容產生對正確變體的呼叫。 您可以在算術運算子一文中深入了解 checked 運算子。

數值 IntPtrUIntPtr

nintnuint 型別現在會分別 System.IntPtrSystem.UIntPtr 別名。

字串插補中的分行符號

字串插補的 {} 字元內的文字現在可以跨越多行。 和 { 標記之間的 } 文字會剖析為 C#。 允許任何合法的 C#,包括分行符號。 此功能可讓您更輕鬆地讀取使用較長 C# 運算式的字串插補,例如模式比對 switch 運算式或 LINQ 查詢。

您可以在語言參考的字串插補一文中深入了解分行符號功能。

清單模式

清單模式會擴充模式比對,以符合清單或陣列中的元素序列。 例如,當 sequence 是陣列或三個整數的清單時 (1、2 和 3),sequence is [1, 2, 3]true。 您可以使用任何模式比對元素,包括常數、類型、屬性和關係模式。 捨棄模式 (_) 符合任何單一元素,而新的範圍模式 (..) 符合零個或多個元素的任何序列。

您可以在語言參考的模式比對文章中深入了解清單模式的詳細資料。

改善的方法群組轉換至委派

方法群組轉換上的 C# 標準現在包含下列項目:

  • 允許轉換 (但非必要) 使用已經包含這些參考的現有委派執行個體。

標準的舊版禁止編譯器重複使用為方法群組轉換所建立的委派物件。 C# 11 編譯器會快取從方法群組轉換建立的委派物件,並重複使用該單一委派物件。 這項功能最初可在 Visual Studio 2022 17.2 版中作為預覽功能,並在 .NET 7 預覽版 2 中使用。

原始字串常值

原始字串常值是字串常值的新格式。 原始字串常值可以包含任意文字,包括空白字元、分行符號、內嵌引號和其他特殊字元,而不需要逸出序列。 原始字串常值以至少三個雙引號開頭 (""") 字元。 並以相同數目的雙引號字元結尾。 一般而言,原始字串常值會在單一行使用三個雙引號來啟動字串,並在個別行使用三個雙引號來結束字串。 開頭引號後面和結尾引號前面的分行符號不會包含在最終內容中:

string longMessage = """
    This is a long message.
    It has several lines.
        Some are indented
                more than others.
    Some should start at the first column.
    Some have "quoted text" in them.
    """;

結尾雙引號左邊的任何空白字元都會從字串常值中移除。 原始字串常值可以與字串插補結合,以在輸出文字中包含大括弧。 多個 $ 字元表示連續大括弧開始和結束插補的數目:

var location = $$"""
   You are at {{{Longitude}}, {{Latitude}}}
   """;

上述範例指定兩個大括弧開始和結束插補。 輸出字串中包含第三個重複的開始大括弧和結束大括弧。

您可以在程式設計指南中的字串文章中深入了解原始字串常值,以及字串常值插補字串的語言參考文章。

自動預設結構

C# 11 編譯器可確保 struct 型別的所有欄位會初始化為其預設值,作為執行建構函式的一部分。 這項變更表示編譯器會自動初始化任何未由建構函式初始化的欄位或 Auto 屬性。 建構函式目前未明確指派所有欄位編譯的結構,且未明確初始化的任何欄位都會設定為其預設值。 您可以在結構一文中深入了解這項變更如何影響結構初始化。

在 常數 string 上模式比對 Span<char>ReadOnlySpan<char>

您能夠使用數個版本的模式比對來測試 string 是否有特定的常數值。 現在,您可以搭配 Span<char>ReadOnlySpan<char> 的變數使用相同的模式比對邏輯。

擴充名稱範圍

在該方法屬性宣告中的 nameof 運算式中使用型別參數名稱和參數名稱現在位於範圍內。 這項功能表示您可以使用 nameof 運算子,在方法或參數宣告的屬性中指定方法參數的名稱。 這項功能最常用於新增可為 Null 分析的屬性。

UTF-8 字串常值

您可以在字串常值上指定 u8 尾碼,以指定 UTF-8 字元編碼。 如果您的應用程式需要 UTF-8 字串,用於 HTTP 字串常數或類似的文字通訊協定,您可以使用這項功能來簡化 UTF-8 字串的建立。

您可以在內建參考型別一文的字串常值一節中深入了解 UTF-8 字串常值。

必要成員

您可以將 required修飾詞新增至屬性和欄位,以強制建構函式和呼叫端初始化這些值。 System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute 可以新增至建構函式,以通知編譯器建構函式初始化所有必要成員。

如需必要成員的詳細資訊,請參閱屬性文章的僅限 init 一節。

ref 欄位和 ref scoped 變數

您可以在 ref struct 內 宣告 ref 欄位。 這支援型別範例包括沒有特殊屬性或隱藏的內部型別的 System.Span<T>

您可以將 scoped 修飾詞新增至任何 ref 宣告。 這會限制參考可以逸出的範圍

檔案本機類型

從 C# 11 開始,您可以使用 file 存取修飾詞來建立類型,其可見度範圍限定於宣告的來源檔案。 此功能可協助來源產生器作者避免命名衝突。 您可以在語言參考中的檔案範圍類型一文中深入了解這項功能。

另請參閱