Using a Dictionary I’m looping over an IEnumerable and apply filters according to the filter dictionary each time. FilterType enum decides what field the filter should be applied to and the string is the freetext filter itself.
The problem I have is that if I add more than one filter to the dictionary (i.e. both a FilterType.Customer and a FilterType.Name filter) the filters will be applied to both the Customer and Name fields BUT the freetext filter will be taken from the first filter added. I.e. in the code below the nameFilterBox.Text gets applied to both the Name and Customer fields in the LINQ query, whereas customerFilterBox.Text doesn’t get applied at all. So the FilterType part of the dictionary gets read twice but the string filter only gets read from the first one.
I really can’t understand why this is happening.
static IEnumerable<Jobb> jobQuery = GetInitialJobQuery();
Dictionary<FilterType, string> filters = new Dictionary<FilterType, string>();
filters.Add(FilterType.Name, nameFilterBox.Text);
filters.Add(FilterType.Customer, customerFilterBox.Text);
foreach (var filter in filters)
{
switch (filter.Key)
{
case FilterType.Customer:
jobQuery = jobQuery.Where(x => x.KUNDREF != null &&
x.KUNDREF.ToLower().Contains(filter.Value.ToLower()));
break;
case FilterType.Name:
jobQuery = jobQuery.Where(x => x.JOBBESKR != null &&
x.JOBBESKR.ToLower().Contains(filter.Value.ToLower()));
break;
}
}
This is the foreach loop variable capturing bug. Your lambdas operate on the last value in
filters, not the one you think.The workaround is to declare a new variable inside the
foreachloop:Alternatively, since you use only
filter.Valueinside the lambdas, you could do this too:Eric Lippert blogged about this here: Closing over the loop variable considered harmful.