提供以下代码:
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();
答案 0 :(得分:13)
调用两个非void返回委托的组合具有语义“调用第一个,丢弃结果,调用第二个,返回结果”。它没有语义“如果它们碰巧返回or
”则称它们为“bool
”。请记住,委托组合必须适用于任何委托类型;为什么运行时应该为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))...