個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Xamarin に関する事を中心に書いています。 Microsoft MVP for Development Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

C# 10 の新機能 - ラムダ式の自然型

C# 10 の新機能の情報の目次は以下をご覧ください。
hiro128.hatenablog.jp 
 

ラムダ式の自然型

ラムダ式に対して Func<...>Action<...> などのデリゲート型を強制的に宣言するのではなく、コンパイラがパラメーターと式の型からデリゲート型を推論し、Func または Action のデリゲートの割り当て、または、デリゲート型の合成が行われる機能です。

var f = (string s) => int.Parse(s);  // Func<string, int>

上記の場合、コンパイラにより、parseFunc<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();

 
公式情報:
Natural types for lambdas
ラムダ式の自然型
 

Minimal API

Minimal API については以下を参照ください。
hiro128.hatenablog.jp