2

次のコードを与えます。

List<string> aux = new List<string>();

aux.Add("a");
aux.Add("ab");
aux.Add("ac");
aux.Add("abc");
aux.Add("b");
aux.Add("bc");
aux.Add("c");
aux.Add("e");
aux.Add("f");

Func<string, bool> searchForA = (f => f.Contains("a"));
Func<string, bool> searchForC = (f => f.Contains("c"));
Func<string, bool> searchForF = (f => f.Contains("f"));

誰かこの電話の理由を説明してくれませんか

aux.Where(searchForA + searchForF + searchForC).ToList();

「ac」、「abc」、「bc」、および「c」を返します。これは、次と同じ結果です。

aux.Where(searchForC).ToList();

つまり、最初のクエリの "a" と "ab" と "F" はどこですか?

編集:検索パターンを動的に定義したいので、デリゲートの組み合わせを使用しました!

EDIT2: 新しいコード例の主要な編集チェック、これは私が解決しようとしている問題です

string[] searchFor = "a c f".Split(' ');

Func<string, bool>[] delegates = new Func<string, bool>[searchFor.Length];
for (int i = 0; i < searchFor.Length; i++)
{
    string search = searchFor[i]; // Make sure the lambda does not capture a loop variable!
    delegates[i] = new Func<string, bool>(f => f.Contains(search));
}

List<string> aux = new List<string>(); 
aux.Add("a");
aux.Add("ab");
aux.Add("ac");
aux.Add("abc");
aux.Add("b");
aux.Add("bc");
aux.Add("c");
aux.Add("e");
aux.Add("f");

List<string> result = aux.Where((Func<string, bool>)Delegate.Combine(delegates)).ToList();
4

1 に答える 1

13

2 つの非 void を返すデリゲートの組み合わせの呼び出しには、「最初の呼び出し、結果の破棄、2 番目の呼び出し、結果の戻り」というセマンティクスがあります。or「両方を呼び出し、たまたま返された場合は結果を返す」というセマンティクスはありませんbool。デリゲートの組み合わせは、どのデリゲート タイプでも機能する必要があることに注意してください。ランタイムは、orセマンティクスではなくブール値を返すデリゲートのセマンティクスを選択する必要があるのはなぜandですか? stringを返し、文字列を連結するデリゲートに対してはどうすればよいですか? int戻ってきたデリゲートを組み合わせる場合、数字を追加する必要がありますか?

結果を組み合わせる問題は、一貫した方法で解決できないため、最後以外はすべて無視することを選択します。

2 つの述語をまとめたい場合orは、自分で簡単に行うことができます。便利な拡張メソッドを次に示します。

static Func<T, bool> Or<T>(this Func<T, bool> f1, Func<T, bool> f2)
{ return t => f1(t) || f2(t); }

そして今、あなたは言うことができます

...Where(searchForA.Or(searchForC).Or(searchForF))...

それを複数のデリゲートに拡張することもできます。

static Func<T, bool> OrMany<T>(params Func<T, bool>[] fs)
{ 
    Func<T, bool> result = t => false;
    foreach(Func<T, bool> f in fs)
        result = result.Or(f);
    return result;
}

これで、デリゲートのリストで「拡張フォーム」を使用できるようになりました。

...Where(OrMany(searchForA, searchForC, searchForf))...

または、デリゲートの配列を含む「展開されていないフォーム」:

Func<string, bool>[] delegates = whatever;
...Where(OrMany(delegates))...
于 2013-03-06T21:07:07.463 に答える