前言
作為.NET 8釋出會的一部分,微軟於11月14日釋出了C#12的新功能,這也是目前.NET的最新版本。正如之前公佈的那樣,最顯著的改進包括了集合表示式、主建構函式、任何型別的別名以及lambda表示式中引數提供預設值。
主建構函式
C#12擴充套件了主建構函式,現在可以在任何class和struct中建立主建構函式。 主建構函式不再侷限於record型別。這一改進允許在類宣告中直接定義建構函式引數。
主建構函式引數的用途有以下三點:
主建構函式引數是在整個類定義範圍內的引數,值得注意的是,編譯器僅在 record 型別(record class 或 record struct 型別)中為主建構函式引數生成公共屬性,從而可以簡化成員管理,下面是主建構函式的程式碼範例:
public class BankAccount(string accountID, string owner)
{
public string AccountID { get; } = accountID;
public string Owner { get; } = owner;
public override string ToString() => $"Account ID: {AccountID}, Owner: {Owner}";
}
集合表示式
集合表示式,簡化了建立各種集合的語法,提供了一種統一的方法,在初始化陣列、列表或跨度時,無需使用不同的語法,以下範例演示了集合表示式的使用:
// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];
// Create a list:
List<string> b = ["one", "two", "three"];
// Create a span
Span<char> c = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];
// Create a jagged 2D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
// Create a jagged 2D array from variables:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[][] twoDFromVariables = [row0, row1, row2];
此外,展開運運算元(集合表示式中的 ..)可將其引數替換為該集合中的元素,引數必須是集合型別,可以簡化多個集合操作的過程。
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[] single = [..row0, ..row1, ..row2];
foreach (var element in single)
{
Console.Write($"{element}, ");
}
// output:
// 1, 2, 3, 4, 5, 6, 7, 8, 9,
ref readonly 引數&內聯陣列
ref readonly 引數和內聯陣列這兩個新功能,可以增強原始記憶體處理能力,提高應用程式效能。內聯陣列使開發人員能夠建立固定大小的 struct 型別陣列,使開發人員能夠優化程式碼以提高效率。內聯陣列速度很快,因為它們依賴於指定長度的精確佈局。內聯陣列是一種具有單個欄位的型別,並用指定陣列長度的InlineArrayAttribute 進行標記。
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
// Usage
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
buffer[i] = i;
foreach (var i in buffer)
Console.WriteLine(i);
此外,C#12還引入了攔截器和Experimental屬性兩個試驗性功能。用 Experimental 特性標記的程式集或模組中宣告的所有型別都是實驗性的。 如果存取其中任何一種型別,編譯器都會發出警告。 可以禁用這些警告以試用實驗性功能。攔截器允許將特定方法呼叫重新路由到不同的程式碼,它適用於一些高階場景,特別是允許更好的提前編譯(AOT)。
lambda 表示式的輸入引數
從C#12開始,Lambda 表示式中的引數可以提供預設值。這意味著可以為元素型別、陣列型別、指標型別或其他不安全型別建立語意別名。
var IncrementBy = (int source, int increment = 1) => source + increment;
Console.WriteLine(IncrementBy(5)); // 6
Console.WriteLine(IncrementBy(5, 2)); // 7
1.非同步 lambda
通過使用 async 和 await 關鍵字,你可以輕鬆建立包含非同步處理的 lambda 表示式和語句。 例如,下面的程式碼範例包含一個調非同步方法 ExampleMethodAsync。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += async (sender, e) =>
{
await ExampleMethodAsync();
textBox1.Text += "\r\nControl returned to Click event handler.\n";
};
}
private async Task ExampleMethodAsync()
{
// The following line simulates a task-returning asynchronous process.
await Task.Delay(1000);
}
}
2.表示式 lambda
表示式位於 => 運運算元右側的 lambda 表示式稱為「表示式 lambda」。 表示式 lambda 會返回表示式的結果,並採用以下基本形式:
(input-parameters) => expression
3.語句 lambda
語句 lambda 與表示式 lambda 類似,只是語句包括在大括號中:
(input-parameters) => { <sequence-of-statements> }
4.lambda 表示式和元組
C# 語言提供對元組的內建支援。 可以提供一個元組作為 Lambda 表示式的引數,同時 Lambda 表示式也可以返回元組。 在某些情況下,C# 編譯器使用型別推理來確定元組元件的型別。
可通過用括號括住用逗號分隔的元件列表來定義元組。 下面的範例使用包含三個元件的元組,將一系列數位傳遞給 lambda 表示式,此表示式將每個值翻倍,然後返回包含乘法運算結果的元組(內含三個元件)。
Func<(int, int, int), (int, int, int)> doubleThem = ns => (2 * ns.Item1, 2 * ns.Item2, 2 * ns.Item3);
var numbers = (2, 3, 4);
var doubledNumbers = doubleThem(numbers);
Console.WriteLine($"The set {numbers} doubled: {doubledNumbers}");
// Output:
// The set (2, 3, 4) doubled: (4, 6, 8)
總結
綜上所述,C#12的新功能為開發者帶來了更多的靈活性、可讀性和效率。無論是是新手還是有經驗的開發者,都能從這些功能中受益。無論是程式碼的編寫、偵錯還是效能優化,C#12為提供了更多的工具和選項。因此,開發者應緊跟技術的步伐,不斷學習和應用C#12的新功能,以保持在C#開發領域的競爭力。
有關C#12可用功能的更多資訊,可存取官方檔案。
擴充套件連結: