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

调用两个非 void 返回委托的组合具有“调用第一个,丢弃结果,调用第二个,返回结果”的语义。它没有语义“or如果它们碰巧返回则调用它们和结果bool”。请记住,委托组合必须适用于任何委托类型;为什么运行时应该or为返回布尔的委托选择语义而不是and语义?对于返回string、连接字符串的委托,它应该做什么?如果你结合int返回的代表,它应该添加数字吗?

组合结果的问题无法以一致的方式解决,因此选择是忽略除最后一个之外的所有结果。

如果您想将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 回答