C# 12 中的新增功能

C# 12 包含下列新功能。 您可以使用最新的 Visual Studio 2022 版本或 .NET 8 SDK 來試用這些功能。

.NET 8 支援 C# 12。 如需詳細資訊,請參閱 C# 語言版本控制

您可以從 .NET 下載頁面下載最新的 .NET 8 SDK。 您也可以下載 Visual Studio 2022,其中包含 .NET 8 SDK。

注意

歡迎您提供這些功能的相關意見反應。 如果您發現上述這些新功能的任何功能,請在 dotnet/roslyn 存放庫中建立新問題

主要建構函式

您現在可以在任何 classstruct 中建立主要建構函式。 主要建構函式不再受限於 record 類型。 主要建構函式參數位於類別整個主體的範圍內。 為了確保已明確指派所有主要建構函式參數,所有明確宣告的建構函式都必須使用 this() 語法來呼叫主要建構函式。 將主要建構函式新增至 class 可防止編譯器宣告隱含無參數建構函式。 在 struct 中,隱含無參數建構函式會初始化所有欄位,包括 0 位元模式的主要建構函式參數。

編譯器只會在 record 類型、record classrecord struct 中,產生主要建構函式參數的公用屬性。 非記錄類別和結構不一定希望主要建構函式參數使用此行為。

您可以在 探索主要建構函式 教學課程以及在 執行個體建構函式 一文中深入了解主要建構函式。

集合運算式

集合運算式引進了新的 terse 語法,以建立一般集合值。 您可以使用散佈運算子 ..,將其他集合內嵌至這些值。

您可以建立數個類似集合的類型,而不需要外部 BCL 支援。 這些類型為:

下列範例顯示集合運算式的使用方式:

// 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:

若要深入了解 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 的語言參考。

實驗屬性

型別、方法和組件可以標示為 System.Diagnostics.CodeAnalysis.ExperimentalAttribute 以表示實驗性功能。 如果您存取以 ExperimentalAttribute 標註的方法或型別,編譯器會發出警告。 以 Experimental 屬性標示組件中宣告的所有型別都是實驗性的。 您可以在 編譯器所讀取的屬性功能規格 中閱讀更多內容。

攔截器

警告

攔截器是實驗性功能,可在預覽模式中與 C# 12 搭配使用。 功能在未來版本中可能會發生中斷性變更或遭到移除。 因此,不建議用於生產或發行的應用程式。

若要使用攔截器,使用者專案必須指定屬性 <InterceptorsPreviewNamespaces>。 這是允許包含攔截器的命名空間清單。

例如:<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>

攔截器是一種方法,可透過在編譯時期對本身的呼叫,以宣告方法式取代對 可攔截 方法的呼叫。 發生此替代動作的方式是讓攔截器宣告其攔截之呼叫的來源位置。 攔截器提供有限的功能,可藉由將新程式碼新增至編譯,例如在來源產生器中,來變更現有程式碼的語意。

您可以使用 攔截器 作為來源產生器的一部分來修改,而不是將程式碼新增至現有的來源編譯。 來源產生器會以對 攔截器 方法的呼叫取代對可攔截方法的呼叫。

如果您有興趣嘗試攔截器,您可以閱讀 功能規格 以深入瞭解。 如果您使用此功能,請務必隨時更新此實驗性功能之功能規格中的任何變更。 如果功能已完成,我們將在此網站上新增更多指導。

另請參閱