none
C#のラムダ式における引数宣言省略(Javaにおけるメソッド参照相当)の正式な仕様について RRS feed

  • 質問

  • C#では、FuncやActionを引数に使用する際に、

    下記の(右部分)のように対象の引数省略を行うことができます。


    var a = Enumerable.Repeat("ddd", 5).Select(string.IsNullOrEmpty);

    var b = Enumerable.Range(0, 10).Select(i => new decimal(i)).Aggregate(decimal.Add);

    この機能は部分的にはJava8以降におけるメソッド参照と同等ですが、

    C#のこの機能には正式な名称はないでしょうか?

    また、この機能の仕様を説明するMSDNのドキュメントがどこかにあれば、教えていただけないでしょうか。


    2017年5月14日 14:27

回答

  • 補足しておくと、AzuleanさんがC# 1.2(VS2003)とC# 3.0(VS2008)を挙げられていますが、質問に書かれている機能はC# 2.0(VS2005)の新機能です(方法 : デリゲートを宣言し、インスタンス化して使用する)。

    方法 : デリゲートを宣言し、インスタンス化して使用する(最新バージョン)にはバージョンごとの説明があります。

    名称としては特になさそうですが、デリゲートのインスタンス化(の簡単な方法)、ぐらいでしょうか。

    2017年5月14日 22:55
  • Azuleanさんが既に書かれているように、.NETにはデリゲートがあります。
    例ではSelectの引数としてFunc<string,bool>が、Aggretageの引数としてFunc<decimal,decimal>というデリゲートが引数の型となっています。
    そして、C#には暗黙の変換というものがあり、デリゲートにおいてもデリゲートと引数が同じメソッドをデリゲートに暗黙に変換することができます。
    つまり引数省略ではなくメソッドがデリゲートに暗黙変換された結果を引数として渡しているという事になります。

    ここら辺は言語仕様書の「6.6メソッドグループの変換」に説明があります。

    var a1 = Enumerable.Repeat("ddd", 5).Select(new Func<string,bool>((s)=>string.IsNullOrEmpty(s)));//匿名メソッドをデリゲートに明示的変換
    var a2 = Enumerable.Repeat("ddd", 5).Select((s) => string.IsNullOrEmpty(s));//デリゲートへ暗黙変換
    
    var a3 = Enumerable.Repeat("ddd", 5).Select(new Func<string, bool>(string.IsNullOrEmpty));//メソッドをデリゲートに明示的変換
    var a4 = Enumerable.Repeat("ddd", 5).Select(string.IsNullOrEmpty);//デリゲートへ暗黙変換


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2017年5月14日 23:38 例追加、書き間違い Func<decimal,bool>->Func<decimal,decimal>
    • 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年5月15日 1:47
    • 回答としてマーク aruki5 2017年5月15日 3:20
    • 回答としてマークされていない aruki5 2017年5月15日 3:23
    • 回答としてマーク aruki5 2017年5月15日 3:24
    2017年5月14日 22:58

すべての返信

  • C# ではメソッド名で関数ポインターのように渡せる書き方が「デリゲート」としてラムダの概念よりも先に登場しています。

    https://msdn.microsoft.com/ja-jp/library/aa288459(v=vs.71).aspx
    (デリゲートに関する説明、VS2003 時点で存在)

    https://msdn.microsoft.com/ja-jp/library/bb383815(v=vs.90).aspx
    (ラムダ式が新機能として紹介、VS2008)

    https://msdn.microsoft.com/ja-jp/library/bb882516(v=vs.90).aspx
    (デリゲートの進化の流れとしてサンプルが書かれている)

    そのため、提起されている内容はラムダ式の1パターンと言うよりは元々あった「デリゲート」と捉えた方が良い気がします。
    ラムダ式が「デリゲート」を渡す際にわざわざクラスやメソッドを書かなくて済む&簡略に書けるようにしたものとして登場しているのだと思います。(匿名関数よりもシンプルに書ける)


    なお、C# の仕様書は Visual Studio のインストール先の VC#\Specifications\1041 に Word 文書で配置されていますので、言語仕様に関する疑問はそちらを読むのも手です。
    (「ラムダ式」と言及している部分は少ないので、今回の疑問には役立ち度が低いかもしれませんが)
    2017年5月14日 21:45
    モデレータ
  • 補足しておくと、AzuleanさんがC# 1.2(VS2003)とC# 3.0(VS2008)を挙げられていますが、質問に書かれている機能はC# 2.0(VS2005)の新機能です(方法 : デリゲートを宣言し、インスタンス化して使用する)。

    方法 : デリゲートを宣言し、インスタンス化して使用する(最新バージョン)にはバージョンごとの説明があります。

    名称としては特になさそうですが、デリゲートのインスタンス化(の簡単な方法)、ぐらいでしょうか。

    2017年5月14日 22:55
  • Azuleanさんが既に書かれているように、.NETにはデリゲートがあります。
    例ではSelectの引数としてFunc<string,bool>が、Aggretageの引数としてFunc<decimal,decimal>というデリゲートが引数の型となっています。
    そして、C#には暗黙の変換というものがあり、デリゲートにおいてもデリゲートと引数が同じメソッドをデリゲートに暗黙に変換することができます。
    つまり引数省略ではなくメソッドがデリゲートに暗黙変換された結果を引数として渡しているという事になります。

    ここら辺は言語仕様書の「6.6メソッドグループの変換」に説明があります。

    var a1 = Enumerable.Repeat("ddd", 5).Select(new Func<string,bool>((s)=>string.IsNullOrEmpty(s)));//匿名メソッドをデリゲートに明示的変換
    var a2 = Enumerable.Repeat("ddd", 5).Select((s) => string.IsNullOrEmpty(s));//デリゲートへ暗黙変換
    
    var a3 = Enumerable.Repeat("ddd", 5).Select(new Func<string, bool>(string.IsNullOrEmpty));//メソッドをデリゲートに明示的変換
    var a4 = Enumerable.Repeat("ddd", 5).Select(string.IsNullOrEmpty);//デリゲートへ暗黙変換


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2017年5月14日 23:38 例追加、書き間違い Func<decimal,bool>->Func<decimal,decimal>
    • 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年5月15日 1:47
    • 回答としてマーク aruki5 2017年5月15日 3:20
    • 回答としてマークされていない aruki5 2017年5月15日 3:23
    • 回答としてマーク aruki5 2017年5月15日 3:24
    2017年5月14日 22:58
  • 佐祐理様、gekka様、Azulean様



    ご回答ありがとうございます。



    C#の場合、あくまで一般的な仕様として

    デリゲートを引数に渡せる+アップキャストの組み合わせが適用され、

    結果としてラムダ式で引数を省略できるということですね。


    お三方を回答としてマークさせていただきます。
    2017年5月15日 14:39