本文內容
- 主構造函數
- 集合表達式
- ref readonly 參數
- 默認 Lambda 參數
顯示另外 5 個
C# 12 包括以下新增功能。 可以使用最新的?Visual Studio 2022?版本或?.NET 8 SDK?嘗試這些功能。
-
主構造函數?- 在 Visual Studio 2022 版本 17.6 預覽版 2 中引入。
-
集合表達式?- 在 Visual Studio 2022 版本 17.7 預覽版 5 中引入。
-
內聯數組?- 在 Visual Studio 2022 版本 17.7 預覽版 3 中引入。
-
Lambda 表達式中的可選參數?- 在 Visual Studio 2022 版本 17.5 預覽版 2 中引入。
-
ref readonly?參數?- 在 Visual Studio 2022 版本 17.8 預覽版 2 中引入。
-
任何類型的別名?- 在 Visual Studio 2022 版本 17.6 預覽版 3 中引入。
-
實驗屬性?- 已在 Visual Studio 2022 版本 17.7 預覽版 3 中引入。
-
攔截器?-?預覽功能?在 Visual Studio 2022 版本 17.7 預覽版 3 中引入。
主構造函數
現在可以在任何?class
?和?struct
?中創建主構造函數。 主構造函數不再局限于?record
?類型。 主構造函數參數都在類的整個主體的范圍內。 為了確保顯式分配所有主構造函數參數,所有顯式聲明的構造函數都必須使用?this()
?語法調用主構造函數。 將主構造函數添加到?class
?可防止編譯器聲明隱式無參數構造函數。 在?struct
?中,隱式無參數構造函數初始化所有字段,包括 0 位模式的主構造函數參數。
編譯器僅在?record
?類型(record class
?或?record struct
?類型)中為主構造函數參數生成公共屬性。 對于主構造函數參數,非記錄類和結構可能并不總是需要此行為。
有關主構造函數的詳細信息,請參閱探索主構造函數的教程和實例構造函數的相關文章。
集合表達式
集合表達式引入了新的 terse 語法來創建常見的集合值。 可以使用展開運算符?..
?將其他集合內聯到這些值中。
可以創建多個類似集合的類型,而無需使用外部 BCL 支持。 這些類型包括:
- 數組類型,例如?
int[]
。 - System.Span<T>?和?System.ReadOnlySpan<T>。
- 支持集合初始值設定項的類型,例如?System.Collections.Generic.List<T>。
以下示例演示了集合表達式的使用:
// 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
?參數
C# 添加了?in
?參數作為傳遞只讀引用的方法。?in
?參數既允許變量和值,并且無需對參數進行任何注釋即可使用。
添加?ref readonly
?參數可以更清楚地了解可能使用?ref
?參數或?in
?參數的 API:
- 即使參數未修改,在?
in
?引入之前創建的 API 也可能會使用?ref
。 可以使用?ref readonly
?更新這些 API。 對于調用方來說,這不會是一項中斷性變更,就像參數?ref
?更改為?in
?那樣。 示例為?System.Runtime.InteropServices.Marshal.QueryInterface。 - 采用?
in
?參數但邏輯上需要變量的 API。 值表達式不起作用。 示例為?System.ReadOnlySpan<T>.ReadOnlySpan<T>(T)。 - 使用?
ref
?的 API,因為它們需要變量,但不改變該變量。 示例為?System.Runtime.CompilerServices.Unsafe.IsNullRef。
若要了解有關?ref readonly
?參數的詳細信息,請參閱有關語言參考中的參數修飾符的文章,或參考只讀參數功能規范。
默認 Lambda 參數
現在可以為 Lambda 表達式的參數定義默認值。 語法和規則與將參數的默認值添加到任何方法或本地函數相同。
可以在有關?Lambda 表達式的文章中詳細了解 Lambda 表達式上的默認參數。
任何類型的別名
可以使用?using
?別名指令創建任何類型的別名,而不僅僅是命名類型。 這意味著可以為元組類型、數組類型、指針類型或其他不安全類型創建語義別名。 有關詳細信息,請參閱功能規范。
內聯數組
運行時團隊和其他庫作者使用內聯數組來提高應用的性能。 內聯數組使開發人員能夠創建固定大小的?struct
?類型數組。 具有內聯緩沖區的結構應提供類似于不安全的固定大小緩沖區的性能特征。 你可能不會聲明自己的內聯數組,但當它們從運行時 API 作為?System.Span<T>?或?System.ReadOnlySpan<T>?對象公開時,你將透明地使用這些數組。
內聯數組的聲明類似于以下?struct
:
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{private int _element0;
}
它們的用法與任何其他數組類似:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{buffer[i] = i;
}foreach (var i in buffer)
{Console.WriteLine(i);
}
區別在于編譯器可以利用有關內聯數組的已知信息。 你可能會像使用任何其他數組一樣使用內聯數組。 有關如何聲明內聯數組的詳細信息,請參閱有關?struct?類型的語言參考。
Experimental 屬性
可以使用?System.Diagnostics.CodeAnalysis.ExperimentalAttribute?來標記類型、方法或程序集,以指示實驗性特征。 如果訪問使用?ExperimentalAttribute?注釋的方法或類型,編譯器將發出警告。 用?Experimental
?特性標記的程序集中包含的所有類型都是實驗性的。 可以在有關編譯器讀取的常規屬性的文章或功能規范中閱讀詳細信息。
攔截器
?警告
攔截器是一項試驗性功能,在 C# 12 的預覽模式下提供。 在將來的版本中,該功能可能會發生中斷性變更或被刪除。 因此,不建議將其用于生產或已發布的應用程序。
若要使用攔截器,用戶項目必須指定屬性?<InterceptorsPreviewNamespaces>
。 這是允許包含攔截器的命名空間的列表。
例如:<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>
攔截器是一種方法,該方法可以在編譯時以聲明方式將對可攔截方法的調用替換為對其自身的調用。 通過讓攔截器聲明所攔截調用的源位置,可以進行這種替換。 攔截器可以向編譯中(例如在源生成器中)添加新代碼,從而提供更改現有代碼語義的有限能力。
在源生成器中使用攔截器修改現有編譯的代碼,而非向其中添加代碼。 源生成器將對可攔截方法的調用替換為對攔截器方法的調用。
如果你有興趣嘗試攔截器,可以閱讀功能規范來了解詳細信息。 如果使用該功能,請確保隨時了解此實驗功能的功能規范中的任何更改。 最終確定功能后,我們將在本站點上添加更多指導。