带有where子句的LINQ语句使执行变慢

Mic*_*ers 2 c# linq

我有一个关于LINQ和where语句的问题.我有以下代码示例(这是我在应用程序中使用的代码的简化版本):

// Get the images from a datasource.
var images = GetImages(); // returns IEnumerable<Image>

// I continue processing images until everything has been processed.
while (images.Any())
{
    // I'm going to determine what kind of image it is and do some actions with it.
    var image = images.First();

    // Suddenly in my process I'm going to add a where statement to my images collection to fetch all images that matches the specified criteria.
    // It can happen (if my images collection is not empty) that the same where statement will be executed again to the images collection.
    // This is also where the problem is, somehow when I don't add the ToList() extension method, my linq statement is becoming slow, really slow.
    // When I add the ToList() extension method, why is my linq statement running fast again?
    var saveImages = images.Where(<criteria>); //.ToList() this is needed to make my LINQ query performant again.

    // I'm going to do something with these save images and then I'm going to remove these save images from the current images collection because I do not need to do these anymore by using the following statement.
    images = images.Except(saveImages);
}
Run Code Online (Sandbox Code Playgroud)

代码示例解释了当我添加ToList()扩展方法时,为什么我的LINQ语句再次变快.为什么我不能仅使用Where语句,因为它返回IEnumerable集合?

我真的很困惑,我希望有人可以向我解释:).

das*_*ght 5

当你经历循环时,你的images第一个就变成了这个

images.Except(firstSetOfExclusions)
Run Code Online (Sandbox Code Playgroud)

那么这个

images.Except(firstSetOfExclusions).Except(secondSetOfExclusions)
Run Code Online (Sandbox Code Playgroud)

那么这个

images.Except(firstSetOfExclusions).Except(secondSetOfExclusions).Except(thirdSetOfExclusions)
Run Code Online (Sandbox Code Playgroud)

等等.缓慢来自这样的事实:除非您调用ToList,否则每组排除项必须执行新查询.随着循环的每次迭代,这变得越来越慢,因为它一遍又一遍地执行相同的查询.ToList通过在内存中"实现"查询来修复它.

请注意,此问题的另一个解决方案是"实现"新的图像子集,如下所示:

images = images.Except(saveImages).ToList();
Run Code Online (Sandbox Code Playgroud)

这将避免链接的"除" S,这样你就不必调用ToListsaveImages.

  • @MichielPeeters你看不到表达式树,因为这**不涉及**表达式树.它与它们毫无关系.它是一系列迭代器块. (2认同)