2011-12-26 9 views
0

参加者はそう、組み合わせることができますlinqで組み合わせたラムダ式が機能しないのはなぜですか?

MethodInvoker del = delegate { Console.WriteLine("Delegate 1"); }; 
del += delegate { Console.WriteLine("Delegate 2"); }; 
del.Invoke(); 

出力:

Delegate 1 
Delegate 2 

それは両方のメソッドを呼び出しているので、私はそれがうまくいくかどうかを確認するために、これを試してみました:

Func<Person, bool> filters = person => person.Name.Contains("John"); 
filters += person => person.Age >= 18; 

List<Person> persons = getPersons(); 

persons.Where(filters); 

しかし、そうでない場合は、最後に適用されます(この場合はperson => person.Age >= 18)。

私の質問は、どうしてですか?これを実装することは可能ですか?注

(ない私はこれを実装するためのLINQの拡張メソッドを書き換えるだろうが、可能な場合はクールになること):

:私は実行が延期されるオブジェクトへのLINQで、これを実行すると、同様であろうことを知っている
persons.Where(x => x.Name.Contains(nameFilter)).Where(x => x.Age >= 18); 

しかし、それは私がに興味があるものではないのです。

+1

2つの 'Func 'デリゲートを組み合わせると、それらを互いに関係させますか?私は非常にそれを疑う。実際には、これらの2人の代理人から値を返すことに注意してください。私は呼び出しリストの最後の戻り値が破棄される前にすべてを想定します。 – BoltClock

+0

どのように動作するのかわかりません。ある関数は結果が偽であり、もう一方の関数は結果が真であると言います。アクションが結合されると、それらは両方とも実行されますが、結果がないので、どの結果を使用するかの問題は発生しません。 – hvd

+1

あなたは、あなたが望むように、Boolを返す代理人を結合するAndとOrメソッドを書くことができます: 'Func And(Func a、Func b){return(Person p) => a(p)&& b(p);} ' – phoog

答えて

5

理由は、両方のフィルタが実行されているということですが、最後のデリゲートの唯一の戻り値が使用されます。これは、デリゲートが仕様に従って動作する方法です。コメントが言うように、私はこれがどのように異なって動作するのか想像できません。結果はANDとなるはずですが、なぜORになるのでしょうか?結果がstringsの場合はどうなりますか?

1

これは、デリゲートコールが1つの結果しか返せないため、Funcデリゲートではなく、アクションデリゲートでのみ機能します。

+0

素晴らしい!これはLinqとエンティティ/ Nhibernateにも使えますか?または、実装に依存しますか? – Andre

+0

@Andre私は、これらのフレームワークがラムダ式ツリーを解析していると推測しています。その場合、ラムダ式を組み合わせることで時間をコンパイルするのではなく、奇妙なランタイムを得ることができます。 –

+0

o/r-mappersへのインタフェースとしてのLinqは、全く異なる方法で動作します。ラムダ式はまったく実行されません。代わりに、その構文構造が分析され、SQL文に変換されます。したがって、マルチキャストは機能しません。 –

関連する問題