次の方法で共有


C# 14 の新機能

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

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

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

新しい機能は、パブリック プレビュー リリースで利用可能になると、[C# の新機能] ページに追加されます。 roslyn 機能ステータス ページワーキング セット セクションは、今後の機能がメイン ブランチにマージされたときに追跡します。 この記事は、.NET 10 Preview 1 で最後に更新されました。

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

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

拡張メンバー

C# 14 では、 拡張メンバーを定義するための新しい構文が追加されています。 新しい構文を使用すると、 拡張 メソッドに加えて拡張プロパティを宣言できます。 型のインスタンスではなく、型を拡張する拡張メンバーを宣言することもできます。 つまり、これらの新しい拡張メンバーは、拡張する型の静的メンバーとして表示できます。 次のコード例は、宣言できるさまざまな種類の拡張メンバーの例を示しています。

public static class Enumerable
{
    // Extension block
    extension<TSource>(IEnumerable<TSource> source) // extension members for IEnumerable<TSource>
    {
        // Extension property:
        public bool IsEmpty => !source.Any();
        // Extension indexer:
        public TSource this[int index] => source.Skip(index).First();

        // Extension method:
        public IEnumerable<TSource> Where(Func<TSource, bool> predicate) { ... }
    }

    // extension block, with a receiver type only
    extension<TSource>(IEnumerable<TSource>) // static extension members for IEnumerable<Source>
    {
        // static extension method:
        public static IEnumerable<TSource> Combine(IEnumerable<TSource> first, IEnumerable<TSource> second) { ... }

        // static extension property:
        public static IEnumerable<TSource> Identity => Enumerable.Empty<TSource>();
    }
}

最初の拡張ブロックのメンバーは、 IEnumerable<TSource>のインスタンス メンバーであるかのように呼び出されます (たとえば、 sequence.IsEmpty)。 2 番目の拡張ブロック内のメンバーは、 IEnumerable<TSource>の静的メンバーであるかのように呼び出されます (例: IEnumerable<int>.Identity)。

詳細については、プログラミング ガイドの 拡張メンバー に関する記事、 extension キーワードに関する言語リファレンス記事、および新しい拡張メンバー 機能の機能仕様 を参照してください。

field キーワード

トークン field を使用すると、明示的なバッキング フィールドを宣言せずにプロパティ アクセサー本体を記述できます。 トークン field は、コンパイラで合成されたバッキング フィールドに置き換えられます。

たとえば、以前は、 string プロパティを null に設定できないようにするには、バッキング フィールドを宣言し、両方のアクセサーを実装する必要がありました。

private string _msg;
public string Message
{
    get => _msg;
    set => _msg = value ?? throw new ArgumentNullException(nameof(value));
}

これで、次のコードを簡略化できます。

public string Message
{
    get;
    set => field = value ?? throw new ArgumentNullException(nameof(value));
}

フィールドでサポートされたプロパティの 1 つまたは両方のアクセサーの本体を宣言できます。

fieldという名前のシンボルを含む型のコードを読み取る場合、破壊的変更や混乱が生じる可能性があります。 @fieldまたはthis.fieldを使用して、field キーワードと識別子の間であいまいさを解消したり、現在のfieldシンボルの名前を変更して区別を深めることができます。

この機能を試してフィードバックがある場合は、 リポジトリのcsharplangにコメントしてください。

field コンテキスト キーワードは、プレビュー機能として C# 13 にあります。

暗黙的なスパン変換

C# 14 では、言語での System.Span<T>System.ReadOnlySpan<T> に対するファースト クラスのサポートが導入されています。 このサポートには、これらの型を使用したより自然なプログラミングを可能にする新しい暗黙的な変換が含まれます。

Span<T>ReadOnlySpan<T> は、C# とランタイムで多くの重要な方法で使用されます。 その導入により、安全性を危険にさらすことなくパフォーマンスが向上します。 C# 14 はリレーションシップを認識し、 ReadOnlySpan<T>Span<T>、および T[]間のいくつかの変換をサポートしています。 スパン型は次のことが可能です: 拡張メソッドのレシーバーになること、他の変換と組み合わせること、ジェネリック型推論のシナリオに役立つこと。

暗黙的なスパン変換の一覧については、言語リファレンス セクションの 組み込み型 に関する記事を参照してください。 詳細については、 ファースト クラススパンタイプの機能仕様を参照してください。

バインドされていないジェネリック型と nameof

C# 14 以降では、 nameof する引数はバインドされていないジェネリック型にすることができます。 たとえば、nameof(List<>)List に評価されます。 以前のバージョンの C# では、 List<int>などの閉じたジェネリック型のみを使用して、 List 名を返すことができました。

修飾子を使用した単純なラムダ パラメーター

パラメーターの型を指定せずに、ラムダ式パラメーターに scopedrefinoutref readonly などのパラメーター修飾子を追加できます。

delegate bool TryParse<T>(string text, out T result);
// ...
TryParse<int> parse1 = (text, out result) => Int32.TryParse(text, out result);

以前は、パラメーター宣言にパラメーターの型が含まれている場合にのみ、修飾子の追加が許可されていました。 上記の宣言では、すべてのパラメーターに対して型が必要です。

TryParse<int> parse2 = (string text, out int result) => Int32.TryParse(text, out result);

params修飾子には、明示的に型指定されたパラメーター リストが必要です。

これらの変更の詳細については、C# 言語リファレンスの ラムダ式 に関する記事を参照してください。

その他の部分メンバー

インスタンス コンストラクターイベント部分メンバーとして宣言できるようになりました。

部分コンストラクターと部分イベントには、定義宣言と実装宣言を 1 つだけ含める必要があります。

部分コンストラクターの実装宣言にのみ、コンストラクター初期化子 ( this() または base()) を含めることができます。 プライマリ コンストラクター構文を含めることができる部分型宣言は 1 つだけです。

部分イベントの実装宣言には、 add アクセサーと remove アクセサーを含める必要があります。 定義宣言は、フィールドに似たイベントを宣言します。

Null 条件付き割り当て

null 条件付きメンバー アクセス演算子 ( ?.?[]) は、代入または複合代入の左側で使用できるようになりました。

C# 14 より前は、プロパティに割り当てる前に変数を null チェックする必要がありました。

if (customer is not null)
{
    customer.Order = GetCurrentOrder();
}

?.演算子を使用すると、上記のコードを簡略化できます。

customer?.Order = GetCurrentOrder();

=演算子の右側は、左側が null でない場合にのみ評価されます。 customerが null の場合、コードはGetCurrentOrderを呼び出しません。

代入に加えて、複合代入演算子 (+=-=など) で null 条件付きメンバー アクセス演算子を使用できます。 ただし、インクリメントとデクリメント( ++--)は許可されません。

詳細については、 条件付きメンバー アクセスnull 条件付き割り当ての機能仕様に関する言語リファレンス記事を参照してください。

こちらも参照ください