做傳銷網(wǎng)站違法什么是軟文營銷?
作者:Kathleen Dollard
排版:Alan Wang
C# 13 已初具雛形,其新特性側(cè)重于靈活性、性能以及使您最喜歡的功能在日常中變得更容易使用。我們以公開的方式構(gòu)建 C#,在今年的 Microsoft Build 大會上,我們會讓您一睹 C# 13 的精彩之處。今天,我們想分享一下 C# 13 當(dāng)前的狀態(tài),以及您今天就可以嘗試的新功能,并提供有關(guān)此版本及以后計劃中的功能更新。讓我們更詳細地了解這些新功能。
- 增強了 params 集合以實現(xiàn)更強的靈活性
- lock 對象
- 索引運算符改進
- 轉(zhuǎn)義序列 \e
- Partial 屬性
- 方法組自然類型改進
- Async 方法和迭代器中的 ref 和 unsafe
- 擴展類型更新
立即試用 C# 13
在我們深入研究 C# 13 的每個新功能之前,您可能想知道如何使用它。
您可以在最新的 .NET 9 預(yù)覽版(撰寫本文時為預(yù)覽版 6)和 Visual Studio 2022-17.11 的最新預(yù)覽版中找到 C# 13 的最新預(yù)覽版。若要訪問預(yù)覽功能,請在項目文件中將您的語言版本設(shè)置為 preview:
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><!--其他設(shè)置--><LangVersion>preview</LangVersion><!--其他設(shè)置--></PropertyGroup>
</Project>
Params 集合
C# 13擴展了 params 關(guān)鍵字,使其適用于可以通過集合表達式構(gòu)造的任何類型。無論是編寫方法還是調(diào)用方法,都增加了靈活性。
當(dāng) params 關(guān)鍵字出現(xiàn)在參數(shù)之前時,對該方法的調(diào)用可以提供零個或多個值的逗號分隔列表。以下內(nèi)容適用于所有版本的 C#:
public void WriteNames(params string[] names)=> Console.WriteLine(String.Join(", ", names));
WriteNames("Mads", "Dustin", "Kathleen");
WriteNames(new string[] {"Mads", "Dustin", "Kathleen"});
// 這兩個都會輸出:Mads、Dustin、Kathleen
請注意,您可以使用逗號分隔的值列表或基礎(chǔ)類型的對象來調(diào)用該方法。
從 C# 13 開始,params 參數(shù)可以是集合表達式支持的任何類型。例如:
public void WriteNames(params List<string> names)=> Console.WriteLine(String.Join(", ", names));
每當(dāng)調(diào)用具有 IEnumerable 參數(shù)的方法時,都可以傳遞 LINQ 表達式的結(jié)果。如果 IEnumerable 參數(shù)具有 params 修飾符,還可以傳遞逗號分隔列表。當(dāng)有常量,可以使用逗號分隔列表;當(dāng)您需要 LINQ 表達式時,您可以使用它:
public void WriteNames(params IEnumerable<string> names)=> Console.WriteLine(String.Join(", ", names));
var persons = new List<Person>
{new Person("Mads", "Torgersen"),new Person("Dustin", "Campbell"),new Person("Kathleen", "Dollard")
};
//以下所有輸出:Mads、Dustin、Kathleen
WriteNames("Mads", "Dustin", "Kathleen");
WriteNames(persons.Select(person => person.FirstName));
WriteNames(from p in persons select p.FirstName);
重載解析
編寫方法時,可以提供多個 params 重載。例如,添加 IEnumerable 重載可支持 LINQ,添加 ReadOnlySpan 或 Span 重載可減少分配,從而可以提高性能。
public void WriteNames(params string[] names)=> Console.WriteLine(String.Join(", ", names));
public void WriteNames(params ReadOnlySpan<string> names)=> Console.WriteLine(String.Join(", ", names));
public void WriteNames(params IEnumerable<string> names)=> Console.WriteLine(String.Join(", ", names));
當(dāng)傳遞指定類型之一時,將使用該重載。當(dāng)傳遞逗號分隔值或不傳遞任何值時,將選擇最佳重載。使用上述重載:
// 使用 IEnumerable 重載
WriteNames(persons.Select(person => person.FirstName));
// 使用數(shù)組重載
WriteNames(new string[] {"Mads", "Dustin", "Kathleen"});
// 使用最有效的過載:當(dāng)前為 ReadOnlySpan
WriteNames("Mads", "Dustin", "Kathleen");
多重重載可以增加便利性并提高性能。庫作者應(yīng)該為所有重載提供相同的語義,這樣調(diào)用者就不需要關(guān)心使用了哪個重載。
Lock 對象
.NET 9 包含一種新的用于互斥的 System.Threading.Lock 類型,比僅在任意 System.Object 實例上進行鎖定更有效。System.Threading.Lock 類型提案詳細介紹了該類型及其創(chuàng)建原因。隨著時間的推移,該類型有望成為 C# 代碼中大多數(shù)鎖定的主要機制。
C# 13 使該類型的使用變得簡單。當(dāng)編譯器識別出 lock 語句的目標是 System.Threading.Lock 對象時,C# 就會生成對 System.Threading.Lock API 的調(diào)用,并在 Lock 實例可能被錯誤地視為普通 object 的情況下提供警告。
此更新意味著 lock 語句的熟悉語法利用了運行時中的新功能。熟悉的代碼只需進行少量更改即可變得更好。只需將項目的 TargetFramework 更改為 .NET 9,并將 lock 的類型從 object 更改為 System.Threading.Lock:
public class MyClass
{private object myLock = new object();public void MyMethod() {lock (myLock){// 您的代碼} }
}
public class MyClass
{// 以下行是唯一的變化private System.Threading.Lock myLock = new System.Threading.Lock();public void MyMethod() {lock (myLock){// 您的代碼} }
}
從初始化器末尾開始的索引
索引運算符 ^ 允許您在可計數(shù)集合中相對于集合末尾指定一個位置。這現(xiàn)在適用于初始化器:
class Program
{ static void Main(){var x = new Numbers{Values = {[1] = 111,[^1] = 999 // 從 C# 13 開始的工作}// x.Values[1] 為 111// x.Values[9] 為 999,因為它是最后一個元素};}
}
class Numbers
{public int[] Values { get; set; } = new int[10];
}
轉(zhuǎn)義序列 \e
C# 13 為眾所熟知的 ESCAPE 或 ESC 字符引入了新的轉(zhuǎn)義序列。以前您必須將其輸入為 \u001b 的變體。當(dāng)使用 VT100/ANSI 轉(zhuǎn)義碼與 System.Console 的終端交互時,此新序列特別方便。例如:
// C# 13 之前版本
Console.WriteLine("\u001b[1mThis is a bold text\u001b[0m");
// 使用 C# 13
Console.WriteLine("\e[1mThis is a bold text\e[0m");
這使得創(chuàng)建精美的終端輸出變得更容易并且更不容易出錯。
Partial 屬性
C# 13 添加了 partial 屬性。與 partial 方法一樣,它們的主要目的是支持源生成器。Partial 方法已在許多版本中可用,并在 C# 9 中進行了額外的改進。Partial 屬性與它們的 partial 方法非常相似。
例如,從 .NET 7(C# 12)開始,正則表達式源生成器為方法創(chuàng)建高效的代碼:
[GeneratedRegex("abc|def")]
private static partial Regex AbcOrDefMethod();
if (AbcOrDefMethod().IsMatch(text))
{// 使用匹配的文本采取行動
}
在 .NET 9(C# 13)中,Regex 源生成器已更新,如果您更喜歡使用屬性,您也可以使用:
[GeneratedRegex("abc|def")]
private static partial Regex AbcOrDefProperty { get; };
if (AbcOrDefProperty.IsMatch(text))
{// 使用匹配的文本采取行動
}
Partial 屬性將使源生成器設(shè)計人員更容易創(chuàng)建自然感覺的 API。
方法組自然類型改進
表達式的自然類型是由編譯器確定的類型,例如當(dāng)類型分配給 var 或 Delegate 時。當(dāng)它是一個簡單類型時,這很簡單。在 C# 10 中,我們添加了對方法組的支持。當(dāng)您將不帶括號的方法名稱作為委托包含時,將使用方法組:
Todo GetTodo() => new(Id: 0, Name: "Name");
var f = GetTodo; // f 的類型是 Func<ToDo>
C# 13 完善了確定自然類型的規(guī)則,以便根據(jù)范圍考慮候選者并刪除沒有成功機會的候選者。更新這些規(guī)則意味著在使用方法組時編譯器錯誤會更少。
allows ref struct
C# 13 添加了一種指定泛型類型參數(shù)功能的新方法。默認情況下,類型參數(shù)不能為 ref struct。但是 C# 13 允許您指定類型參數(shù)可以是 ref struct,并應(yīng)用相應(yīng)的規(guī)則。雖然其他泛型約束限制了可用作類型參數(shù)的類型集,但此新規(guī)范擴展了允許的類型。我們認為這是一種反約束,因為它刪除了限制,而不是添加了限制。where 子句中的語法 allows ref struct,其中 allows 表示用法上的擴展:
T Identity<T>(T p)where T : allows ref struct=> p;
// Okay
Span<int> local = Identity(new Span<int>(new int[10]));
使用 allows ref struct 指定的類型參數(shù)具有 ref struct 類型的所有行為和限制。
Async 方法和迭代器中的 ref 和 unsafe
在 C# 13 之前,迭代器方法(使用 Yield Return 的方法)和 async 方法不能聲明局部 ref 變量,也不能具有 unsafe 的上下文。
在 C# 13 中,async 方法可以聲明 ref 局部變量,或 ref struct 類型的局部變量。這些變量不能跨 await 邊界或 Yield return 邊界保存。
同樣,C# 13 允許迭代器方法中使用 unsafe 上下文。但是,所有 Yield Return 和 Await 語句都必須在safe上下文中。這些放寬的限制讓您可以在更多地方使用 ref 局部變量和 ref struct類型。
擴展類型的更新
我們對 Mads 和 Dustin 在 Build 上展示的擴展類型功能感到非常興奮。我們還在 Build 上的博客文章 .NET 公告中介紹了擴展類型。當(dāng)時,我們的目標是在 C# 13中實現(xiàn)該功能的關(guān)鍵部分,但設(shè)計和實現(xiàn)將需要更多的時間。請在早期的 C# 14(NET 10)預(yù)覽版中查找擴展類型。
總結(jié)
您可以在 C# 13 的新增功能中了解更多相關(guān)內(nèi)容。我們?nèi)栽跒?C# 13 開發(fā)新功能,您可以在 Roslyn 功能狀態(tài)頁面查看我們正在做的事情。此外,請務(wù)必關(guān)注 .NET 9 預(yù)覽版發(fā)行說明,您現(xiàn)在可以在其中找到每個版本的 C# 發(fā)行說明。
請下載帶有 .NET 9 的 Visual Studio 2022-17.11 的最新預(yù)覽版,體驗這些新功能,并告訴我們您的想法!