C#,使用多个 .Where() 语句过滤 IEnumerable,性能下降

Ana*_*ion 0 c# linq performance ienumerable linq-to-entities

我有一个 IEnumerable,我正在通过 .Where 表达式对其应用多个过滤器。我的代码看起来像这样

public List<MyObject> FilteringFunction(List<MyObject> listToFilter, List<Filter> filters)
{
    // A dirty way to have an enumerable instead of List
    var enumerableToFilter = listToFilter.Where(x => true);

    foeach(var filter in filters)
    {
        enumerableToFilter = enumerableToFilter.Where(x => x.Value.Contains(filter.Value));
    }

    return enumerableToFilter.ToList();

}
Run Code Online (Sandbox Code Playgroud)

我是否只遍历我的集合一次?(因为我只有一个使用 LINQ to SQL 的数据库调用)

Kel*_*all 5

Enumerables 推迟执行,直到您对其进行迭代,并且在整个集合的单次迭代中应用多个过滤器。结合其他 linq 语句可能会强制提前枚举,我没有测试过每种组合。这只会是非常大的数据集或低规格性能关键系统的问题。

这是一个使用 Visual Studios c# Interactive 的示例

> class Item
. {
.     private int _number;
.     public int Number
.     {
.         get { Console.WriteLine($"Got number {_number}"); return _number; }
.         set { _number = value; }
.     }
. }
> 
> IEnumerable<Item> items = new List<Item>() { 
.     new Item { Number = 1 },
.     new Item { Number = 2 },
.     new Item { Number = 3 },
.     new Item { Number = 4 },
.     new Item { Number = 5 },
.     new Item { Number = 6 }
. };
> 
> var filteredItems = items.Where(item => item.Number > 3).Where(item => item.Number % 2 == 0);
> 
> var listedItems = filteredItems.ToList();
Got number 1
Got number 2
Got number 3
Got number 4
Got number 4
Got number 5
Got number 5
Got number 6
Got number 6
> 
Run Code Online (Sandbox Code Playgroud)

请注意,1、2 和 3 已被过滤掉,并且不会对它们调用第二个过滤器方法。4、5 和 6 都通过了第一个过滤器,因此应用了两个过滤器。

关键点:请注意,在将可枚举项读取到列表之前,过滤实际上不会发生。您将能够继续附加过滤器,直到将结果枚举到列表中。