轉載:?C# 13 中的新增功能 | Microsoft Learn
C# 13 包括以下新增功能。 可以使用最新的?Visual Studio 2022?版本或?.NET 9 SDK?嘗試這些功能:Introduced in Visual Studio 2022 Version 17.12 and newer when using C# 13+
C# 13 中的新增功能 | Microsoft Learn
- params?集合
- 新的?lock?類型和語義。
- 新的轉義序列 -?\e。
- 方法組自然類型改進
- 對象初始值設定項中的隱式索引器訪問
- 在迭代器和異步方法中啟用?ref?局部變量和?unsafe?上下文
- 啟用?ref struct?類型來實現接口。
- 允許在泛型中將 ref 結構類型?作為類型參數的參數。
partial
?類型中現在允許使用部分屬性和索引器。- 重載解析優先級允許庫作者指定一種重載優于其他重載。
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?集合的功能規范中了解更多信息。
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
?后面的下一個字符是有效的十六進制數字,則那些字符會成為轉義序列的一部分。
方法組自然類型
此功能對涉及方法組的重載解析進行了少量優化。?方法組是一個方法,并且所有重載都具有相同的名稱。 編譯器以前的行為是為方法組構造完整的候選方法集。 如果需要自然類型,則自然類型是根據整套候選方法確定的。
新行為是在每個作用域內削減候選方法集,移除那些不適用的候選方法。 通常,被刪除的方法是具有錯誤參數或不滿足約束的泛型方法。 只有在沒有找到候選方法的情況下,該過程才會繼續到下一個外部作用域。 此過程更緊密地遵循重載決策的一般算法。 如果在給定作用域內找到的所有候選方法都不匹配,則該方法組沒有自然類型。
您可以在?提案規范中查看更改的詳細信息。
隱式索引訪問
現在在對象初始化表達式中允許使用隱式“從末尾”索引運算符^
。 例如,你現在可以在對象初始值設定項中初始化數組,如以下代碼所示:
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
?類包括一個?buffer
?數組,其初始化長度為 10。 前面的示例使用“從末尾”索引操作符 (^
) 為數組賦值,從而有效地創建了一個從 9 開始倒數到 0 的數組。
在 C# 13 之前的版本中,對象初始化器中不能使用?^
?運算符。 你需要從前面開始為元素編制索引。
迭代器和?async
?方法中的?ref
和?unsafe
該功能和以下兩個功能使?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 return
?和?yield 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 安全性。?ref struct
?中的顯式接口方法聲明只能通過類型參數訪問,而該類型參數為?allows ref struct。 此外,ref struct
?類型必須實現接口中聲明的所有方法,包括默認實現的方法。
有關?ref struct?類型?和新增?allows ref struct?泛型約束的更多信息,請參閱更新。
更多部分成員
可以在 C# 13 中聲明?partial
?屬性和?partial
?索引器。 部分屬性和索引器通常遵循與?partial
?方法相同的規則:創建一個?聲明聲明,一個實現聲明。 這兩種聲明的簽名必須匹配。 一個限制是,不能使用自動屬性聲明來實現部分屬性。 未聲明正文的屬性被視為聲明聲明。
public partial class C
{// Declaring declarationpublic 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
?的字段,則在讀取代碼時可能會出現重大更改或混淆。 可以使用?@field
?或?this.field
?來消除?field
?關鍵字和標識符之間的歧義。
?重要
field
?關鍵字是 C# 13 中的一項預覽功能。 必須使用 .NET 9,并在項目文件中將?<LangVersion>
?元素設置為?preview
,才能使用?field
?上下文關鍵字。在有名為?
field
?的字段的類中使用?field
?關鍵字功能時應小心謹慎。 新的?field
?關鍵字在屬性訪問器的范圍內隱藏一個名為?field
?的字段。 可以更改?field
?變量的名稱,或者使用?@
?令牌將?field
?標識引用為?@field
。 可以通過閱讀?field關鍵字的功能規范來了解詳細信息。
另請參閱
- .NET 9 的新增功能