C# 11 的新功能

C# 11 中新增了下列功能:

您可以下載最新的 Visual Studio 2022。 您也可以使用 .NET 7 SDK 試用所有這些功能,您可以從 .NET 下載頁面下載

注意

我們對這些功能的意見反應感興趣。 如果您發現上述任何新功能的問題,請在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# Tuple 語法的元組類型) 。

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

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

泛型數學支援

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

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

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

您可以在 探索靜態抽象介面成員.NET 6 – 一般數學部落格文章中的預覽功能 教學課程中自行深入瞭解並試用此功能。

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

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

數值 IntPtrUIntPtr

nuint 現在 nint 會分別輸入別名 System.IntPtrSystem.UIntPtr

字串內插補點中的分行符號

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

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

清單模式

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

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

已改善方法群組轉換為委派

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

  • 允許 (轉換,但不需要) 使用已包含這些參考的現有委派實例。

舊版的標準禁止編譯器重複使用為方法群組轉換建立的委派物件。 C# 11 編譯器會快取從方法群組轉換建立的委派物件,並重複使用該單一委派物件。 這項功能首次在 Visual Studio 2022 17.2 版中提供作為預覽功能,以及 .NET 7 Preview 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 屬性。 建構函式目前未明確指派所有欄位編譯的結構,且未明確初始化的任何欄位都會設定為其預設值。 您可以在結構一文中深入瞭解這項變更如何影響結構初始化。

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

您能夠使用數個版本的模式比對來測試 是否有 string 特定的常數值。 現在,您可以搭配 或 ReadOnlySpan<char> 的變數 Span<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 存取修飾詞來建立類型,其可見度範圍限定于宣告的來源檔案。 此功能可協助來源產生器作者避免命名衝突。 您可以在語言參考中的 檔案範圍類型 一文中深入瞭解這項功能。

另請參閱