C#14新機能

C#14 新機能 F01_明示的な型を指定せずにラムダパラメータでパラメータ修飾子を使用する

C# 14では、delegateがref・out・inなどのパラメータ修飾子を使っている場合、そのdelegateをラムダ式で呼び出すときに、パラメータの型指定を省略できるようになりました。今回はこの新機能を、実際にサンプルコードを作りながら確認していきます。

対象となるパラメータ修飾子: ref, out, in

パラメータ修飾子とdelegateの関係

パラメータ修飾子とは、ref・out・inのように、メソッドの引数の渡し方を指定するキーワードのことです。今回のテーマは、delegateでref・out・inなどのパラメータ修飾子を指定している場合に、そのdelegateをラムダ式で呼び出すときの型指定を省略できるというものです。

例えば、何か文字列を渡してチェックし、変更した内容を呼び出し元に返す、というイメージのdelegateを考えます。voidを返すCheckというdelegateを定義し、引数はref stringのtargetとします。このCheckのdelegateを使う共通処理のメソッドとして、targetの文字列とCheckのdelegateを受け取るCommonCheckを用意しておきます。呼び出し元が指定したチェック処理が、CommonCheckの内部から呼び出される、という仕組みです。

Check delegateとCommonCheckメソッドの定義例

サンプルを作成する

実際にVisual Studio 2026でWindowsフォームアプリ(.NET 10)のプロジェクトを新規作成し、サンプルコードを作っていきます。ClassAを用意し、その中にvoid Checkというdelegateを、ref stringのtarget引数で定義します。

ClassAにCheckのdelegateを定義

続いて、このCheckのdelegateを使う共通関数として、public static void CommonCheckを作成します。引数はtargetのstringとCheckのdelegateです。内部では何らかの処理の後にcheck(ref target)を呼び出し、呼び出し元が指定したチェック処理を実行します。

CommonCheckメソッドの実装

メソッドを指定して呼び出す

まずは通常のメソッドとしてCheckAを作成し、これをCommonCheckの第2引数に渡す方法を確認します。CheckAの引数と戻り値は、Checkのdelegateと同じ形にしておきます(引数はref string、戻り値はvoid)。呼び出し側では、string型のvalueを用意し、ClassA.CommonCheck(ref value, CheckA)という形で呼び出します。

CheckAメソッドを定義してCommonCheckに渡す

これをデバッグ実行すると、CommonCheckが呼ばれた際にcheckのところで自分が指定したCheckAが実行され、valueが”aaa”に変更されることが確認できます。

デバッグ実行でCheckAが呼び出される様子(value = “aaa”)

ラムダ式で書く

次に、CheckAのような専用メソッドを自前で作るのではなく、ラムダ式でその場に処理を書く方法を確認します。CommonCheckの第2引数に、(ref string target) => { target = “bbb”; } という形でラムダ式を渡します。ref stringという型指定付きの書き方は、これまで通りC# 13でも可能な書き方です。

ラムダ式で(ref string target) => {…}と型を明示して呼び出す

これをデバッグ実行すると、ラムダ式で指定した処理が実行され、valueが”bbb”に変更されることが確認できます。

型指定を省略する(C# 14の新機能)

ここからが今回の本題です。上記のref stringのstringの部分、つまりパラメータの型指定を省略できるようになったというのがC# 14の新機能です。まず、ターゲットフレームワークを.NET 9に変更してみます。

プロジェクトのターゲットフレームワークを確認する画面

.NET 9.0を選択する

.NET 9(C# 13相当)の状態で、ラムダ式の引数からstringを省略して(ref target) => {…}と書くと、コンパイルエラーになります。エラーメッセージは「CS9260: 機能’単純なラムダ パラメーター修飾子’はC# 13.0では使用できません。14.0以上の言語バージョンを使用してください。」という内容です。

C# 13(.NET 9)ではCS9260のコンパイルエラーが発生する

ターゲットフレームワークを.NET 10(C# 14)に戻すと、同じ(ref target) => {…}という書き方でもエラーが出ず、正しく動作します。targetの型がstringであることはCommonCheckの定義(Checkのdelegate)から推論できるため、わざわざstringと書かなくてもよいということです。

C# 14では(ref target) => {…}と型を省略しても動作する

Microsoft Learnの解説

この機能はMicrosoft Learnの「C# 14の新機能」ページにも「修飾子を使用した単純なラムダ パラメーター」として掲載されています。パラメーターの型を指定せずに、ラムダ式パラメーターにscoped、ref、in、out、ref readonlyなどのパラメーター修飾子を追加できる、と説明されています。

Microsoft Learn「C# 14の新機能」ページの該当箇所

まとめ

今回はrefパターンで確認しましたが、ref以外にもscoped、in、out、ref readonlyの合わせて5パターンで、型を省略した書き方が可能です。ただし、この省略が使えるのはdelegateを使っている場合に限られます。ActionやFuncではそもそもref・out・inといった修飾子自体を使えないため、今回の変更が関係するのは、delegateでref・out・inなどを使っている部分をラムダ式で呼び出す場合のみです。

もともと型を書いても問題なく動いていた部分なので、実務上の恩恵はそれほど大きくないかもしれませんが、型が明らかな場合に省略して簡潔に書けるようになった、という改善です。

public class ClassA
{
  public delegate void Check(ref string target);

  public static void CommonCheck(string target, Check check)
  {
    //処理・・・
    check(ref target);
  }
}

// C# 14: 型指定を省略できる
string value = "";
ClassA.CommonCheck(ref value, (ref target) =>
{
  target = "bbb";
});
C#14 新機能