Consider the following code (albeit, a little contrived, but it’s a major simplification of a real-world program):
string[] strings = { "ab", "abcd", "abc", "ac", "b", "abcde", "c", "bc" };
string[] filters = { "a", "b", "c" };
// iteratively apply each filter
IEnumerable<string> filteredStrings = strings.ToArray();
foreach (string filter in filters)
{
// in my real-world program lots of processing and stuff
// happens here, hence why i need the enclosing foreach loop
filteredStrings = filteredStrings.Where(s => s.Contains(filter));
}
As you can see, the code iteratively filters an array of strings down to a smaller set of strings. When the for-each loop finishes, filteredStrings should be the subset of strings that pass all filters. In this example, that would be:
{ "abcd", "abc", "abcde" }
However, the output I get is:
{ "abcd", "abc", "ac", "abcde", "c", "bc" }
It seems to only be filtering out those strings not containing "c", which I presume has something to do with it being the last filter. I guess I must not be chaining IEnumerable.Where() in the correct way. What’s going on here and how can I get the right output?
And yes, that foreach loop needs to remain intact, as per the comments in my code.
The where delegate isn’t capturing the local variable in the way you expect. Variable
filteris changing, and it’s using the last result in all of the wheres, because Linq does lazy evaluation.Copy the iteration variable to a local var, and I believe it will capture the way you expect.