31

質問のタイトルを適切に表現したことを願っています。

C# では、(デリゲートとして) ラムダを使用するか、古いデリゲート構文を使用してこれを行うことができます。

Func<string> fnHello = () => "hello";
Console.WriteLine(fnHello());

Func<string> fnHello2 = delegate()
{
    return "hello 2";
};
Console.WriteLine(fnHello2());

では、ラムダまたはデリゲートの本体を「インライン化」して、名前付き変数にキャプチャする (匿名にする) ことができないのはなぜでしょうか?

// Inline anonymous lambda not allowed
Console.WriteLine(
    (() => "hello inline lambda")()
);

// Inline anonymous delegate not allowed
Console.WriteLine(
    (delegate() { return "hello inline delegate"; })()
);

JavaScript で動作する例 (比較のみ) は次のとおりです。

alert(
    (function(){ return "hello inline anonymous function from javascript"; })()
);

これにより、予想されるアラート ボックスが生成されます。

更新:適切にキャストすれば、C# でインラインの匿名ラムダを使用できるようですが、() の量によって手に負えなくなり始めます。

// Inline anonymous lambda with appropriate cast IS allowed
Console.WriteLine(
    ((Func<string>)(() => "hello inline anonymous lambda"))()
);

おそらく、コンパイラは匿名デリゲートの署名を推測して、どの Console.WriteLine() を呼び出そうとしているのかを知ることができませんか? この特定のキャストが必要な理由を知っている人はいますか?

4

4 に答える 4

25

C# のラムダには、デリゲートまたは Expression 型にキャストするコンテキストで使用されるまで、型がありません。だから言えないんだよ

var x = () => "some lambda";

あなたは楽しむかもしれません

http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part-two.aspx

http://blogs.msdn.com/ericlippert/archive/2007/01/12/lambda-expressions-vs-anonymous-methods-part-three.aspx

于 2010-04-22T02:51:11.230 に答える
16

タイプキャストを与えるとうまくいくようです:

String s = ((Func<String>) (() => "hello inline lambda"))();

無駄ですか?完全ではありません。以下を取る:

String s;
{
    Object o = MightBeNull();
    s = o == null ? "Default value" : o.ToString();
}

これを考慮してください:

String S = ((Func<Object,String>)(o => o == null ? "Default value" : o.ToString())
    )(MightBeNull());

少し見にくいですが、コンパクトです。

于 2012-11-14T14:29:50.093 に答える
9

を記述するFunc<string> = ...と、コンパイラは 型のオブジェクトを作成する必要があることを認識しますFunc<string>。しかし、そのデリゲートをインラインで記述すると、コンパイラはどのタイプのオブジェクトを作成する必要があるかわかりません。

上記のことから、明白な結論を導き出すことができます: コンパイラに型を明示的に伝えるだけです!

Console.WriteLine( new Func<string>( () => "Hello" )() );

アップデート

わかりました、私が答えを書いている間に、あなたは投稿を更新しました。上記の私の答えは、「なぜこの特定のタイプが必要なのか」という質問にすでに答えていると思います。繰り返しますが、コンパイラは作成するタイプのオブジェクトを認識していないためです。

ここで、「コンパイラは匿名デリゲートの sig を推測できない」部分について少し詳しく説明します。おわかりのように、JavaScript とは異なります。C# には、一般的な "関数" (または "メソッド") 型はありません。各デリゲートには、明示的に指定された署名と型名が必要です。また、デリゲートを作成する場合、コンパイラは型を認識している必要があります。

これで、匿名オブジェクト型 (別名 ) の場合と同様に、コンパイラがその場でデリゲート型を構築できることを暗示する方法がわかりますnew { a = 1, b = "xyz" }。しかし、ちょっと考えてみてください。とにかく、そのようなデリゲートはおそらく役に立たないでしょう。つまり、そのメソッドは最初に引数の型を宣言する必要があるため、別のメソッドに渡すことはできません。また、名前付きの型が必要なので、それからイベントを作成できます。

そんな感じ...

于 2010-04-22T03:10:09.417 に答える
2

Delegate パラメーターを受け取るメソッドには、インライン ラムダ式を使用できます。

ただし、わずかな落とし穴があります。パラメーターが基本 Delegate 型として型指定されている場合は、明示的に Delegate の特定の派生型 (たとえば Action) にキャストする必要があります。そうでなければ、コンパイラは文句を言うでしょう。

類似の質問:
Invoke 呼び出しの
匿名メソッド 匿名メソッドとデリゲート

于 2010-04-22T03:06:36.683 に答える