C# 12 の新機能

C# 12 では、いくつかのプレビュー機能が導入されています。 最新の Visual Studio プレビューまたは最新の .NET 8 プレビュー SDK を使うことで、これらの機能を試すことができます。

プライマリ コンストラクター

すべての classstruct で、プライマリ コンストラクターを作成できるようになりました。 プライマリ コンストラクターは、record 型に制限されなくなりました。 プライマリ コンストラクターのパラメーターは、クラスの本体全体のスコープに含まれます。 プライマリ コンストラクターのすべてのパラメーターが確実に割り当てられるようにするには、明示的に宣言されたすべてのコンストラクターで、this() 構文を使ってプライマリ コンストラクターを呼び出す必要があります。 プライマリ コンストラクターを class に追加すると、コンパイラで暗黙的なパラメーターなしのコンストラクターが宣言されなくなります。 struct では、暗黙的なパラメーターなしのコンストラクターによってすべてのフィールドが初期化され、これにはプライマリ コンストラクター パラメーターの 0 ビット パターンへの初期化が含まれます。

コンパイラは、record 型 (record class または record struct 型) についてのみプライマリ コンストラクター パラメーターのパブリック プロパティを生成します。 record クラスと struct 以外では、プライマリ コンストラクター パラメーターに対するこの動作が常に必要であるとは限りません。

プライマリ コンストラクターの詳細については、プライマリ コンストラクターの探索に関するチュートリアルと、インスタンス コンストラクターに関する記事を参照してください。

コレクション式

コレクション式は、共通のコレクション値を作成するための新しい簡潔な構文を導入します。 これらの値に他のコレクションをインライン化するために、スプレッド演算子 .. を使用できます。

外部 BCL サポートの必要なく、いくつかのコレクションのような型を作成できます。 これらの型には、次のようなものがあります。

次に、コレクション式の使用例を示します。

// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];

// Create a span
Span<int> b  = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];

// Create a 2 D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

// create a 2 D 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,

スプレッド演算子のオペランドは、列挙可能な式です。 スプレッド演算子は、列挙式の各要素を評価します。

要素のコレクションが必要な場合は、どこでもコレクション式を使用できます。 コレクションの初期値を指定したり、コレクション型を受け取るメソッドの引数として渡したりすることができます。 コレクション式の詳細については、コレクション式言語リファレンスの記事、または機能仕様を参照してください。

既定のラムダ パラメーター

ラムダ式のパラメーターに既定値を定義できるようになりました。 構文と規則は、任意のメソッドまたはローカル関数に引数の既定値を追加する場合と同じです。

ラムダ式での既定のパラメーターについて詳しくは、ラムダ式に関する記事をご覧ください。

任意の型の別名設定

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に関する言語リファレンスを参照してください。

インターセプター

警告

インターセプターは試験的な機能であり、C# 12 のプレビュー モードで使用できます。 この機能は、今後のリリースで破壊的変更を受ける、または削除される可能性があります。 そのため、運用環境またはリリースされたアプリケーションにはお勧めしません。

インターセプターを使用するには、プロジェクト ファイルで <Features>InterceptorsPreview</Features> 要素を設定する必要があります。 このフラグがないと、たとえ他の C# 12 機能が有効になっている場合でも、インターセプターは無効です。

インターセプターは、インターセプト可能なメソッドに対する呼び出しを、コンパイル時にそれ自体の呼び出しで宣言的に置き換えることができるメソッドです。 この置換は、インターセプターにインターセプトする呼び出しのソースの場所を宣言させることによって発生します。 インターセプターにより、たとえばソース ジェネレーターなどにおいて、コンパイルに新しいコードを追加することで、既存コードのセマンティクスを変更する機能が制限されます。

インターセプターはソース ジェネレーターの一部として、既存ソース コンパイルにコードを追加するのではなく、コードを変更するために使用します。 ソース ジェネレーターは、インターセプト可能メソッドの呼び出しを "インターセプター" メソッドの呼び出しで置き換えます。

インターセプターの試用をご検討の場合は、「機能仕様」をお読みになり詳細をご確認ください。 この機能を使用する場合は、このプレビュー機能の機能仕様のどんな変更も見逃さないように注意してください。 この機能が完成したら、このサイトにさらにガイダンスを追加します。

関連項目