C# 10 の新機能

C# 10 によって、C# 言語に次の機能と機能強化が追加されています。

C# 10 は .NET 6 でサポートされています。 詳細については、「C# 言語のバージョン管理」を参照してください。

最新の .NET 6 SDK は .NET のダウンロード ページからダウンロードできます。 .NET 6 SDK を含む Visual Studio 2022 をダウンロードすることもできます。

注意

これらの機能に関するご意見とご感想をお寄せください。 これらの新機能のいずれかに問題がある場合は、dotnet/roslyn リポジトリに新しい問題を作成します。

レコード構造体

record struct または readonly record struct 宣言を使用して、値型レコードを宣言できます。 record class 宣言を使用して、record が参照型であることを明確にできるようになりました。

構造体型の機能強化

C# 10 では、構造体型に関連する次の機能強化が導入されています。

  • 構造体型でインスタンスのパラメーターなしのコンストラクターを宣言し、その宣言でインスタンス フィールドまたはプロパティを初期化することができます。 詳細については、「構造体型」の記事の構造体の初期化と既定値に関するセクションを参照してください。
  • withの左側のオペランドは、任意の構造体型にすることも、匿名 (参照) 型にすることもできます。

補間された文字列ハンドラー

補間された文字列式から結果の文字列を作成する型を作成できます。 .NET ライブラリでは、多くの API でこの機能が使用されています。 こちらのチュートリアルに従って構築することができます。

グローバルな using ディレクティブ

global 修飾子を任意の using ディレクティブに追加すれば、コンパイル時にディレクティブをすべてのソース ファイルに適用するようにコンパイラに指示できます。 これに該当するのは、通常、プロジェクト内のすべてのソース ファイルです。

ファイル スコープの名前空間の宣言

新しい形式の namespace 宣言を使用することで、後続のすべての宣言が宣言された名前空間のメンバーであることを宣言できます。

namespace MyNamespace;

この新しい構文は、namespace 宣言の水平と垂直の両方のスペースの節約につながります。

拡張プロパティのパターン

C# 10 以降、入れ子になったプロパティまたはプロパティ パターン内のフィールドを参照できます。 たとえば、フォームのパターン

{ Prop1.Prop2: pattern }

は、C# 10 以降で有効で、以下と同じです

{ Prop1: { Prop2: pattern } }

これは、C# 8.0 以降で有効です。

詳細については、機能提案ノートの「拡張プロパティ パターン」を参照してください。 プロパティ パターンの詳細については、「パターン」の記事の「プロパティ パターン」セクションを参照してください。

ラムダ式の機能強化

C# 10 には、ラムダ式の処理方法に多くの機能強化が加えられています。

  • ラムダ式には自然型があり、コンパイラによってラムダ式またはメソッド グループからデリゲート型を推測できます。
  • ラムダ式には、コンパイラによって推測できない場合に、戻り値の型を宣言できます。
  • 属性はラムダ式に適用できます。

このような機能があるため、ラムダ式はメソッドとローカル関数に似ています。 これにより、デリゲート型の変数を宣言することなく、ラムダ式を簡単に使用できます。また、新しい ASP.NET Core Minimal API とよりシームレスに連携します。

定数の補間文字列

C# 10 では、すべてのプレースホルダー自体が定数文字列の場合、文字列補間を使用して const 文字列を初期化できます。 文字列補間では、アプリケーションで使用される定数文字列を構築するときに、より読みやすい定数文字列を作成できます。 プレースホルダー式は、実行時にそれらの定数が文字列に変換されるため、数値定数にすることはできません。 現在のカルチャは、それらの文字列形式に影響を与える可能性があります。 詳細については、言語リファレンスの constに関するページを参照してください。

レコードの型で ToString を封印することができる

C# 10 では、レコードの型で ToString をオーバーライドするときに sealed 修飾子を追加できます。 ToString メソッドを封印すると、コンパイラで派生レコード型に対して ToString メソッドを合成できなくなります。 sealedToString により、すべての派生レコード型で共通の基本レコード型で定義された ToString メソッドが確実に使用されるようになります。 この機能の詳細については、この記事のレコードに関する記述を参照してください。

同じ分解内の代入と宣言

この変更により、以前のバージョンの C# からの制限がなくなります。 以前は、分解ですべての値を既存の変数に代入したり、新しく宣言された変数を初期化したりすることができました。

// Initialization:
(int x, int y) = point;

// assignment:
int x1 = 0;
int y1 = 0;
(x1, y1) = point;

C# 10 では、この制限がなくなります。

int x = 0;
(x, int y) = point;

限定代入の機能強化

C# 10 より前のバージョンでは、限定代入と null 状態分析によって擬陽性である警告が生成されるシナリオが多くありました。 通常、これらには、ブール値定数との比較、if ステートメント内の true または false ステートメントでのみ変数にアクセスすること、null 合体式が含まれていました。 これらの例では、以前のバージョンの C# では警告が生成されていましたが、C# 10 では生成されません。

string representation = "N/A";
if ((c != null && c.GetDependentValue(out object obj)) == true)
{
   representation = obj.ToString(); // undesired error
}

// Or, using ?.
if (c?.GetDependentValue(out object obj) == true)
{
   representation = obj.ToString(); // undesired error
}

// Or, using ??
if (c?.GetDependentValue(out object obj) ?? false)
{
   representation = obj.ToString(); // undesired error
}

この機能強化の主な影響は、限定代入と null 状態分析の警告がより正確になったことです。

メソッドで AsyncMethodBuilder 属性を許可する

C# 10 以降では、特定のタスクのような型を返すすべてのメソッドに対してメソッド ビルダー型を指定するだけでなく、1 つのメソッドに対して別の非同期メソッド ビルダーを指定することができます。 カスタム非同期メソッド ビルダーにより、特定のメソッドでカスタム ビルダーのベネフィットが得られる高度なパフォーマンス チューニング シナリオが可能になります。

詳細については、コンパイラによって読み取られる属性についての記事の AsyncMethodBuilder に関するセクションを参照してください。

CallerArgumentExpression 属性の診断

System.Runtime.CompilerServices.CallerArgumentExpressionAttribute を使って、コンパイラによって別の引数のテキスト表現に置き換えられるパラメーターを指定できます。 この機能を使うと、ライブラリからより具体的な診断を作成できるようになります。 次のコードを使うと、条件をテストできます。 条件が false の場合、例外メッセージには condition に渡された引数のテキスト表現が含まれています。

public static void Validate(bool condition, [CallerArgumentExpression("condition")] string? message=null)
{
    if (!condition)
    {
        throw new InvalidOperationException($"Argument failed validation: <{message}>");
    }
}

この機能の詳細については、呼び出し元情報の属性に関する記事の言語リファレンス セクションを参照してください。

拡張 #line pragma

C# 10 は、#line pragma の新しい形式をサポートしています。 この新しい形式を使わない可能性もありますが、その効果はわかるはずです。 この機能強化により、Razor などのドメイン固有の言語 (DSL) で、よりきめ細かい出力が可能になります。 Razor エンジンによってこれらの拡張機能が使われ、デバッグ エクスペリエンスが向上します。 デバッガーで Razor ソースをより正確に強調表示できることがわかります。 新しい構文の詳細については、言語リファレンスのプリプロセッサ ディレクティブに関する記事を参照してください。 また、Razor ベースの例については、機能仕様に関する記事を参照してください。