2016-07-05 8 views
1

匿名関数は、この関数を呼び出す必要があるので、匿名関数を無名関数に変換するまで、匿名関数は名前付き関数ほど強力ではないと思っていました。簡単な例:希望匿名関数は非匿名関数と同じくらい役に立ちます

public void Init(List<int> numbers, List<string> texts) 
{ 
    int n = GetFirst(numbers); 
    string t = GetFirst(texts); 
} 

private T GetFirst<T>(List<T> list) 
{ 
    return list[0]; 
} 

GenFunc<T, List<T>, T> getFirst = list => list[0]; 

ようなものを定義し、代わりに、インスタンスメソッドGetFirstのものを使用することであろう。 Funcを使用することは不可能です。これは、ジェネリックパラメータが異なるセマンティックを持つためです。私は、したがって、デリゲート(Funcの「ベース」)

delegate T GetFirstDelegate<T>(List<T> list); 

定義が、私は、定義された一般的なパラメータを使用して、それをインスタンス化することができ、例えば

GetFirstDelegate<string> getFirst = list => list[0]; 

が、私は、プレースホルダの一般的なパラメータを持つには希望しないよう:

GetFirstDelegate<T> getFirst = list => list[0]; 

これは私が匿名メソッドは、名前のメソッドとしてmightlyないと思います - 少なくとも、一般的な使用量の面で - またはAM私は何かを欠いている?

+0

、あなたのために例えば、LINQは既にIEnumerに '.First()'を定義していますできれば ' –

答えて

1

ような
Func<List<T>, T> getFirst<T> = list => list[0]; 

一般的な変数を作成することです。しかし、変数は、一般的なことができないとして残念ながらこれは有効なC#ではありません。型(インターフェイス、クラス、構造体)、デリゲート、およびメソッドのみが汎用である可能性があります。

2

質問:this質問を見ると、C#では一般的な匿名関数が使用できないことがわかります。コンパイラが通常の汎用メソッドと関係している場合のイメージング。実際に呼び出された各タイプのオーバーロードが発生します(少なくとも単純化すると)。汎用パラメータで変数を宣言するとき、このインスタンスではどのようにコンパイラを実行する必要がありますか?異なる汎用パラメータで新しい変数を生成することはできません。

これは明らかです。基本的には、ジェネリックメソッドとクラスはコンパイル時のことであることを知っておく必要があります。あなたが実際にやろうとしている何

0

List<T>を入力として受け取り、Tを返す関数のシグネチャは、Func<List<T>, T>であり、Func<T, List<T>, T>ではありません。

私はこれがあなたが望んだと思う:

private Func<List<T>, T> GenGetFirst<T>() 
{ 
    return list => list[0]; 
} 

は使用方法:

public void Init(List<int> numbers, List<string> texts) 
{ 
    int n = GenGetFirst<int>()(numbers); 
    string t = GenGetFirst<string>()(texts); 
} 

以上明確のように:もちろん

public void Init(List<int> numbers, List<string> texts) 
{ 
    Func<List<int>, int> intFunc = GenGetFirst<int>(); 
    Func<List<string>, string> stringFunc = GenGetFirst<string>(); 

    int n = intFunc(numbers); 
    string t = stringFunc(texts); 
} 
+0

私はあなたの答えをありがとうが、私は名前付きのメソッドを取り除き、私が学んだようなC#では不可能な無名関数で表現したかったのです。 – David