C# 10 の新機能の情報の目次は以下をご覧ください。
hiro128.hatenablog.jp
ラムダ式の自然型
ラムダ式に対して Func<...>
や Action<...>
などのデリゲート型を強制的に宣言するのではなく、コンパイラがパラメーターと式の型からデリゲート型を推論し、Func または Action のデリゲートの割り当て、または、デリゲート型の合成が行われる機能です。
var f = (string s) => int.Parse(s); // Func<string, int>
上記の場合、コンパイラにより、parse
を Func<string, int>
と推論することができます。上記のように当てはまる Func または Action が存在する場合、コンパイラには Func または Action のデリゲートが使われます。 それ以外の場合デリゲート型が合成されます。 たとえば、ラムダ式のパラメーターが ref の場合や、パラメータの数が多い場合などはコンパイラによって型が合成されます。
なお、ラムダ式が自然型の場合、System.Object、System.Delegate などの曖昧な型に割り当てることができます。
(後述しますが、この、ラムダの自然型は、System.Object、System.Delegate に割り当て可能というところがポイントになります。)
object f = (string s) => int.Parse(s); // Func<string, int> Delegate f = (string s) => int.Parse(s); // Func<string, int>
導入の意図
明示的なデリゲート型なしでラムダとメソッドグループを使用できるようになるため、本来明示的なデリゲート型を定義して割り当てる必要があるメソッドのパラメータに対して明示的なキャストなしでパラメーターと式の型を合わせた任意のラムダを割り当て可能になります。
こちらも「ソースコードを簡潔にするための機能」です。
わかりやすい例として、この機能は ASP.NET の Minimal API (最小限のコードで表現する REST API)のシナリオで便利です。
.NET 6 では以下のオーバーロードが MapGet 拡張メソッドに追加されています。(Delegate handler パラメータに注目してください。)
public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapGet (this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Delegate handler);
MapGet(IEndpointRouteBuilder, String, Delegate)
上記のように、MapGet メソッドで Microsoft.AspNetCore.Http.RequestDelegate
ではなく、Delegate
を利用できるようになりました。
さらに、ラムダ式が自然型の場合、System.Delegate に割り当て可能になったため、下記のコードのように、明示的なデリゲート型へのキャストなしでラムダを記述できるようになり、余計な括弧や型が不必要になって直感的に読みやすいコードになりました。
using System; using System.Linq; using Microsoft.AspNetCore.Builder; var app = WebApplication.Create(args); app.MapGet("/", () => "Hello Minimal API !"); // ラムダの自然型によりラムダを直接割り当てられる app.MapGet("/", (Func<string>)(() => "Hello Minimal API !")); // ラムダの自然型を使用しない場合、明示的な Func<string> へのキャストが必要 await app.RunAsync();
Minimal API
Minimal API については以下を参照ください。
hiro128.hatenablog.jp