前言
作爲.NET 8發佈會的一部分,微軟於11月14日發佈了C#12的新功能,這也是目前.NET的最新版本。正如之前公佈的那樣,最顯著的改進包括了集合表達式、主構造函數、任何類型的別名以及lambda表達式中參數提供默認值。
主構造函數
C#12擴展了主構造函數,現在可以在任何class和struct中創建主構造函數。 主構造函數不再侷限於record類型。這一改進允許在類聲明中直接定義構造函數參數。
主構造函數參數的用途有以下三點:
- 作爲 base() 構造函數調用的參數
- 初始化成員字段或屬性
- 引用實例成員中的構造函數參數
主構造函數參數是在整個類定義範圍內的參數,值得注意的是,編譯器僅在 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可用功能的更多信息,可訪問官方文檔。
擴展鏈接: