C# 13 の新機能

C# 13 には、次の新機能が含まれています。 最新の Visual Studio 2022 バージョンまたは .NET 9 SDKを使用して、これらの機能を試すことができます。

Visual Studio 17.12 以降、C# 13 には、プレビュー機能として field コンテキスト キーワードが含まれています。

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

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

C# 13 で導入された破壊的変更については、破壊的変更に関する記事を参照してください。

手記

これらの機能に関するフィードバックに関心があります。 これらの新機能のいずれかに問題がある場合は、dotnet/roslyn リポジトリで新しい問題を作成してください。

params コレクション

params 修飾子は配列型に限定されません。 paramsSystem.Span<T>System.ReadOnlySpan<T> を実装し、System.Collections.Generic.IEnumerable<T> メソッドを持つ型など、認識された任意のコレクション型で Add を使用できるようになりました。 具象型に加えて、インターフェイス System.Collections.Generic.IEnumerable<T>System.Collections.Generic.IReadOnlyCollection<T>System.Collections.Generic.IReadOnlyList<T>System.Collections.Generic.ICollection<T>、および System.Collections.Generic.IList<T> も使用できます。

インターフェイス型を使用すると、コンパイラは指定された引数のストレージを合成します。 詳細については、 params コレクションの C# 言語仕様を参照してください。

たとえば、メソッド宣言では、スパンを params パラメーターとして宣言できます。

public void Concat<T>(params ReadOnlySpan<T> items)
{
    for (int i = 0; i < items.Length; i++)
    {
        Console.Write(items[i]);
        Console.Write(" ");
    }
    Console.WriteLine();
}

新しいロック オブジェクト

.NET 9 ランタイムには、スレッド同期用の新しい型 (System.Threading.Lock 型) が含まれています。 この型は、API を使用してスレッドの同期を向上させます。 Lock.EnterScope() メソッドは、排他的スコープを入力します。 そこから返される ref struct は、排他スコープを終了する Dispose() パターンをサポートします。

C# lock ステートメントは、ロックのターゲットが Lock オブジェクトであるかどうかを認識します。 その場合は、System.Threading.Monitorを使用する従来の API ではなく、更新された API を使用します。 コンパイラは、Lock オブジェクトを別の型に変換し、Monitor ベースのコードが生成されるかどうかを認識します。 詳細については、 新しいロック オブジェクトの C# 言語仕様を参照してください。

この機能を使用すると、lock するオブジェクトの種類を変更することで、新しいライブラリの種類の利点を得ることができます。 他のコードを変更する必要はありません。

新しいエスケープ シーケンス

\e 文字 (Unicode ) のESCAPEのエスケープ シーケンスとして U+001B を使用できます。 以前は、\u001b または \x1bを使用しました。 \x1b の後の次の文字が有効な 16 進数の場合、それらの文字がエスケープ シーケンスの一部になったため、1b を使用することはお勧めしません。

メソッド グループ自然型

この機能により、メソッド グループを含むオーバーロードの解決に対して小さな最適化が行われます。 メソッドグループ は、同じ名前のメソッドとそのすべてのオーバーロードから構成されています。 以前の動作は、コンパイラがメソッド グループの候補メソッドの完全なセットを構築するためでした。 自然型が必要な場合、自然型は候補メソッドの完全なセットから決定されました。

新しい動作では、各スコープで候補メソッドのセットを排除し、該当しない候補メソッドを削除します。 通常、削除されたメソッドは、間違ったアリティを持つジェネリック メソッド、または満たされていない制約です。 このプロセスは、候補のメソッドが見つからない場合にのみ、次の外部スコープに進みます。 このプロセスは、オーバーロード解決の一般的なアルゴリズムに従います。 特定のスコープで見つかったすべての候補メソッドが一致しない場合、メソッド グループには自然な型はありません。

C# 言語仕様の 匿名関数型 句の変更の詳細を読み取ることができます。

インデックスへの暗黙のアクセス

単一次元コレクションのオブジェクト初期化子式で、暗黙的な "from the end" インデックス演算子 ( ^) が許可されるようになりました。 たとえば、次のコードに示すように、オブジェクト初期化子を使用して単一次元配列を初期化できるようになりました。

public class TimerRemaining
{
    public int[] buffer { get; set; } = new int[10];
}

var countdown = new TimerRemaining()
{
    buffer =
    {
        [^1] = 0,
        [^2] = 1,
        [^3] = 2,
        [^4] = 3,
        [^5] = 4,
        [^6] = 5,
        [^7] = 6,
        [^8] = 7,
        [^9] = 8,
        [^10] = 9
    }
};

TimerRemaining クラスには、長さ 10 に初期化された buffer 配列が含まれています。 前の例では、"from the end" インデックス演算子 (^) を使用してこの配列に値を割り当て、実質的に 9 から 0 までカウントダウンする配列を作成します。

C# 13 より前のバージョンでは、^ 演算子をオブジェクト初期化子で使用することはできません。 要素のインデックスを前面から作成する必要があります。

反復子の refunsafe および async メソッド

この機能と次の 2 つの機能により、ref struct 型で新しいコンストラクトを使用できます。 独自の ref struct 型を記述しない限り、これらの機能は使用しません。 より多くの場合、間接的な利点は System.Span<T> として見られ、より多くの機能 System.ReadOnlySpan<T> 得られます。

C# 13 より前のバージョンでは、反復子メソッド (yield returnを使用するメソッド) と async メソッドは、ローカル ref 変数を宣言することも、unsafe コンテキストを持つこともできませんでした。

C# 13 では、async メソッドは、ref ローカル変数または ref struct 型のローカル変数を宣言できます。 ただし、これらの変数には、await 境界を越えてアクセスすることはできません。 どちらも、yield return 境界を越えてアクセスすることはできません。

この緩やかな制限により、コンパイラは、より多くの場所で ref ローカル変数と ref struct 型を検証可能に安全に使用できます。 これらのメソッドでは、System.ReadOnlySpan<T> のような型を安全に使用できます。 安全規則に違反しているかどうかをコンパイラから通知されます。

同様に、C# 13 では反復子メソッドで unsafe コンテキストを使用できます。 ただし、すべての yield return ステートメントと yield break ステートメントは、安全なコンテキストにある必要があります。

allows ref struct

C# 13 より前では、ref struct 型をジェネリック型またはメソッドの型引数として宣言できませんでした。 これで、ジェネリック型宣言にアンチ制約(allows ref struct)を追加できるようになりました。 この反制約では、その型パラメーターに指定された型引数を ref struct 型にできることを宣言します。 コンパイラは、その型パラメーターのすべてのインスタンスに ref 安全規則を適用します。

たとえば、次のコードのようなジェネリック型を宣言できます。

public class C<T> where T : allows ref struct
{
    // Use T as a ref struct:
    public void M(scoped T p)
    {
        // The parameter p must follow ref safety rules
    }
}

これにより、System.Span<T>System.ReadOnlySpan<T> などの型を汎用アルゴリズムで使用できます (該当する場合)。 詳細については、where の更新プログラムと、一般的な制約 に関するプログラミング ガイドの記事を参照してください。

ref struct インターフェイス

C# 13 より前では、ref struct 型はインターフェイスの実装を許可されていませんでした。 C# 13 以降では、可能です。 ref struct 型がインターフェイスを実装することを宣言できます。 ただし、ref 安全規則を確保するために、ref struct 型をインターフェイス型に変換することはできません。 その変換はボックス化変換であり、参照の安全性を侵害する可能性があります。 ref struct の明示的なインターフェイス メソッド宣言は、その型パラメーターが allows ref structという条件を満たす場合にのみ、型パラメーターを介してアクセス可能です。 また、ref struct 型は、既定の実装を持つメソッドを含め、インターフェイスで宣言されているすべてのメソッドを実装する必要があります。

ref struct の更新と allows ref struct ジェネリック制約の追加について詳しく知る。

その他の部分メンバー

C# 13 では、partial プロパティと partial インデクサーを宣言できます。 一般に、部分プロパティとインデクサーは、partial メソッドと同じ規則に従います。宣言 を宣言する を 1 つ作成し、1 つ 宣言実装します。 2 つの宣言のシグネチャが一致している必要があります。 制限の1つは、が部分プロパティを実装する際に、自動プロパティ宣言 を使用できないことです。 本体を宣言しないプロパティは、 宣言宣言と見なされます。

public partial class C
{
    // Declaring declaration
    public partial string Name { get; set; }
}

public partial class C
{
    // implementation declaration:
    private string _name;
    public partial string Name
    {
        get => _name;
        set => _name = value;
    }
}

詳細については、部分メンバー に関する記事を参照してください。

オーバーロード解決の優先順位

C# 13 では、コンパイラは、1 つのオーバーロードを別のオーバーロードよりも優先する OverloadResolutionPriorityAttribute を認識します。 ライブラリ作成者は、この属性を使用して、既存のオーバーロードよりも新しいより優れたオーバーロードが優先されるようにすることができます。 たとえば、パフォーマンスの高い新しいオーバーロードを追加できます。 ライブラリを使用する既存のコードを中断する必要はありませんが、ユーザーが再コンパイルするときに新しいバージョンに更新する必要があります。 オーバーロード解決優先度 を使用して、どのオーバーロードを優先するかをコンパイラに通知できます。 優先順位が最も高いオーバーロードが優先されます。

この機能は、ライブラリ作成者が新しいオーバーロードを追加するときにあいまいさを回避することを目的としています。 ライブラリの作成者は、混乱を避けるために、この属性に注意を払う必要があります。

field キーワード

field コンテキスト キーワードは、プレビュー機能として C# 13 にあります。 トークン field は、プロパティ アクセサーのコンパイラ合成バッキング フィールドにアクセスします。 これにより、型宣言で明示的なバッキング フィールドを宣言せずにアクセサー本体を記述できます。 フィールドでサポートされたプロパティの 1 つまたは両方のアクセサーの本体を宣言できます。

field 機能はプレビュー機能としてリリースされます。 私たちはそれを使用してあなたの経験から学びたいです。 fieldというフィールドが含まれる型のコードを読み取る際には、破壊的変更が発生する可能性や混乱を招く恐れがあります。 @field または this.field を使用して、field キーワードと識別子の間であいまいさを解消できます。

重要

fieldという名前のフィールドを持つクラスでは、field キーワード機能の使用に注意する必要があります。 新しい field キーワードは、プロパティ アクセサーのスコープ内の field という名前のフィールドをシャドウします。 field 変数の名前を変更するか、@ トークンを使用して field 識別子を @fieldとして参照できます。 詳細については、field キーワードの機能仕様を参照してください。

この機能を試してフィードバックがある場合は、 リポジトリの csharplang に追加します。

関連項目