共用方式為


C# 13 的新功能

C# 13 包含下列新功能。 您可以使用最新的 Visual Studio 2022 版本或 .NET 9 SDK來嘗試這些功能:

從 Visual Studio 17.12 開始,C# 13 會以預覽功能的形式包含 field 內容關鍵詞。

C# 13 受到 .NET 9的支持。 如需詳細資訊,請參閱 C# 語言版本設定。

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

新功能會在公開預覽版本中提供時,新增至 [C# 的新功能] 頁面。 roslyn 功能狀態頁面 追蹤即將推出的功能合併至主要分支時,工作集 區段。

您可以在我們的文章中找到 C# 13 引入的任何重大變更,詳見 重大變更

注意

我們對這些功能的意見反應有興趣。 如果您發現任何上述新功能的問題,請在 dotnet/roslyn 存放庫中建立 新問題

params 集合

params 修飾詞不僅限於陣列類型。 您現在可以將 params 用於任何可辨識的集合類型,包括 System.Span<T>System.ReadOnlySpan<T>,以及實作 System.Collections.Generic.IEnumerable<T> 且包含 Add 方法的類型。 除了具體類型,也可以使用介面 System.Collections.Generic.IEnumerable<T>System.Collections.Generic.IReadOnlyCollection<T>System.Collections.Generic.IReadOnlyList<T>System.Collections.Generic.ICollection<T>System.Collections.Generic.IList<T>

使用介面類型時,編譯程式會合成所提供自變數的記憶體。 您可以在 params 集合的功能規格中深入瞭解。

例如,方法宣告可以將範圍宣告為 params 參數:

public void Concat<T>(params ReadOnlySpan<T> items)
{
    for (int i = 0; i < items.Length; i++)
    {
        Console.Write(items[i]);
        Console.Write(" ");
    }
    Console.WriteLine();
}

新的鎖定物件

.NET 9 運行時間包含線程同步處理的新類型,System.Threading.Lock 類型。 此類型透過其 API 提供更佳的線程同步處理。 Lock.EnterScope() 方法會進入專有範圍。 傳回的 ref struct 支援 Dispose() 模式來退出獨佔範圍。

C# lock 語句會辨識鎖定的目標是否為 Lock 物件。 如果是,它會使用更新的 API,而不是使用 System.Threading.Monitor的傳統 API。 如果您將 Lock 物件轉換成另一種類型,而且會產生以 Monitor 為基礎的程式代碼,編譯程式也會辨識。 您可以在 新鎖定物件的功能規格中了解更多信息。

這項功能可讓您透過變更物件 lock的類型,以獲得新庫類型的優點。 不需要變更其他程序代碼。

新的逸出序列

您可以使用 \e 作為用於 ESCAPE 字元的 Unicode U+001B字元字面值 轉義序列。 先前,您已使用 \u001b\x1b。 不建議使用 \x1b,因為如果 1b 後面的下一個字元是有效的十六進位數位,這些字元就會成為逸出序列的一部分。

方法群組自然類型

這項功能可對涉及方法群組的多載解析進行小型優化。 方法群組 是方法,而且所有多載的名稱相同。 先前的行為是讓編譯程式建構方法群組的完整候選方法集合。 如果需要自然類型,則自然類型是從完整的候選方法集合決定。

新的行為是在每個範圍內篩選候選方法組,移除那些不適用的候選方法。 一般而言,移除的方法是具有錯誤參數個數的泛型方法,或未滿足的約束條件。 只有在找不到候選方法時,流程才會繼續進行到下一個外部範圍。 此程式更緊密地遵循多載解析的一般演算法。 如果在指定範圍中找到的所有候選方法都不符合,則方法群組沒有自然類型。

您可以在 提案規格中閱讀更動的詳細資料。

隱含索引存取

物件初始化表示式現在允許隱含的「from the end」索引運算子^。 例如,您現在可以在物件初始化運算式中初始化陣列,如下列程式代碼所示:

public class TimerRemaining
{
    public int[] buffer { get; set; } = new int[10];
}

var countdown = new TimerRemaining()
{
    buffer =
    {
        [^1] = 0,
        [^2] = 1,
        [^3] = 2,
        [^4] = 3,
        [^5] = 4,
        [^6] = 5,
        [^7] = 6,
        [^8] = 7,
        [^9] = 8,
        [^10] = 9
    }
};

TimerRemaining 類別包含初始化為長度為 10 的 buffer 陣列。 上述範例使用「從結尾」索引運算子(^),有效地建立了一個從 9 倒數到 0 的陣列,並指派數值給它。

在 C# 13 之前的版本中,無法在物件初始化表示式中使用 ^ 運算子。 您需要從頭開始為元素建立索引。

迭代器和 async 方法中的 refunsafe

此功能和下列兩個功能可讓 ref struct 類型使用新的建構。 除非您撰寫自己的 ref struct 類型,否則您不會使用這些。 您可能更會看到當 System.Span<T>System.ReadOnlySpan<T> 獲得更多功能時的間接好處。

在 C# 13 之前,反覆運算器方法(使用 yield return的方法)和 async 方法無法宣告局部 ref 變數,也無法擁有 unsafe 內容。

在 C# 13 中,async 方法可以宣告 ref 局部變數或 ref struct 類型的局部變數。 不過,這些變數無法跨 await 界限存取。 兩者都無法跨 yield return 界限存取。

這項寬鬆的限制可讓編譯程式在更多地方安全地使用 ref 局部變數和 ref struct 類型。 您可以在這些方法中安全地使用 System.ReadOnlySpan<T> 這類類型。 編譯程式會告訴您是否違反安全規則。

同樣地,C# 13 允許反覆運算器方法中的 unsafe 內容。 不過,所有 yield returnyield break 語句都必須在安全的情境中。

allows ref struct

在 C# 13 之前,ref struct 類型無法宣告為泛型型別或方法的類型自變數。 現在,泛型型別宣告可以新增反條件約束,allows ref struct。 這個反條件約束會宣告提供給該類型參數的類型自變數可以是 ref struct 類型。 編譯程式會對該類型參數的所有實例強制執行 ref 安全規則。

例如,您可以宣告泛型類型,例如下列程序代碼:

public class C<T> where T : allows ref struct
{
    // Use T as a ref struct:
    public void M(scoped T p)
    {
        // The parameter p must follow ref safety rules
    }
}

這可讓 System.Span<T>System.ReadOnlySpan<T> 等類型與適用的泛型演算法搭配使用。 您可以在 where 更新和程序設計指南一文中深入瞭解 泛型條件約束

ref struct 介面

在 C# 13 之前,不允許 ref struct 類型實作介面。 從 C# 13 開始,這些功能可以實現。 您可以宣告 ref struct 類型實作介面。 不過,為了確保 ref 安全規則,ref struct 類型無法轉換成介面類型。 該轉換是拳擊轉換,而且可能會違反 ref safety。 ref struct 中的明確介面方法宣告只能透過類型參數來存取,其中該類型參數 allows ref struct。 此外,ref struct 類型必須實作介面中宣告的所有方法,包括具有預設實作的方法。

進一步了解 ref struct 型別的相關更新,,以及加入了 allows ref struct 泛型約束條件。

更多次要成員

您可以在 C# 13 中宣告 partial 屬性和 partial 索引器。 部分屬性和索引器通常遵循與 partial 方法相同的規則:您會建立一個 宣告宣告,另一個 實作宣告。 兩個宣告的簽章必須相符。 其中一個限制是您無法使用自動屬性宣告,實作部分屬性。 未聲明主體的屬性被視為 的宣告。

public partial class C
{
    // Declaring declaration
    public partial string Name { get; set; }
}

public partial class C
{
    // implementation declaration:
    private string _name;
    public partial string Name
    {
        get => _name;
        set => _name = value;
    }
}

您可以在文章中深入瞭解 部分成員

重載解析優先順序

在 C# 13 中,編譯程式會辨識 OverloadResolutionPriorityAttribute 偏好一個多載而不是另一個多載。 函式庫作者可以使用這個屬性來確保新的、更好的多載被優先於現有的多載。 例如,您可以新增效能較強的新多載。 您不想中斷使用連結庫的現有程序代碼,但您希望使用者在重新編譯時更新為新版本。 您可以使用 多載解析優先順序,通知編譯程式應該首選某個多載。 優先選擇優先順序最高的多載。

這項功能是設計給程式庫作者,讓他們在新增多載時避免模棱兩可的情況。 連結庫作者應謹慎使用此屬性,以避免混淆。

field 關鍵詞

field 內容關鍵詞位於 C# 13 中作為預覽功能。 令牌 field 存取屬性存取子中由編譯器生成的支援欄位。 它可讓您撰寫存取子主體,而不需要在類型宣告中宣告明確的支援欄位。 您可以為以欄位支援的屬性,定義單個或雙個存取子的主體。

field 功能會以預覽功能的形式發行。 我們想要從您的體驗中學習。 在類型中包含名為 field的欄位時,可能會發生潛在的重大變更或在讀取程式碼時造成混淆。 您可以使用 @fieldthis.field 來釐清 field 關鍵詞與標識符之間的混淆。

重要

field 關鍵詞是 C# 13 中的預覽功能。 您必須使用 .NET 9,並將您的 <LangVersion> 元素設定為項目檔中的 preview,才能使用 field 內容關鍵詞。

您應該小心在具有名為 field欄位的類別中使用 field 關鍵詞功能。 新的 field 關鍵詞會遮蔽屬性存取子範圍中名為 field 的欄位。 您可以變更 field 變數的名稱,或使用 @ 令牌將 field 識別元參考為 @field。 您可以閱讀 field 關鍵詞的規格說明來深入瞭解。

如果您嘗試此功能並有意見反應,請將其新增到 csharplang 存放庫中的 功能問題

另請參閱