Give the following piece of code:
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"));
Can someone please explain to me why this call
aux.Where(searchForA + searchForF + searchForC).ToList();
returns "ac", "abc", "bc" and "c" which is the same result as
aux.Where(searchForC).ToList();
I mean, wheres "a" and "ab" and "F" on the first query?
EDIT: I used the delegate combination because I want to define dynamically the search pattern!
EDIT2: Major edit check for new piece of example code, this the problem im tryng to solve
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();
Invoking the combination of two non-void returning delegates has the semantics "call the first, discard the result, call the second, return the result". It doesn't have the semantics "call them both and or the results if they happen to return bool". Remember, delegate combination has to work for any delegate type; why should the runtime choose or semantics for bool-returning delegates instead of and semantics? What should it do for delegates that return string, concatenate the strings? If you combine int returning delegates should it add the numbers?
The problem of combining results is not solvable in a consistent way, so the choice is to ignore all but the last.
If you want to or two predicates together then you can easily do so yourself. Here's a handy extension method:
static Func<T, bool> Or<T>(this Func<T, bool> f1, Func<T, bool> f2)
{ return t => f1(t) || f2(t); }
and now you can say
...Where(searchForA.Or(searchForC).Or(searchForF))...
You could also extend that to multiple delegates:
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;
}
And now you can use "expanded form" with a list of delegates:
...Where(OrMany(searchForA, searchForC, searchForf))...
or "unexpanded form" with an array of delegates:
Func<string, bool>[] delegates = whatever;
...Where(OrMany(delegates))...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With