编译器是否连接LINQ where查询?

本文关键字:查询 where LINQ 是否 连接 编译器 | 更新日期: 2023-09-27 18:08:11

考虑下面两个类似的代码示例。

1个where条款

bool validFactory
  = fields
    .Where(
      fields => field.FieldType == typeof( DependencyPropertyFactory<T> ) &&
                field.IsStatic )
    .Any();

两个where条款

bool validFactory
  = fields
    .Where( field => field.FieldType == typeof( DependencyPropertyFactory<T> ) )
    .Where( field => field.IsStatic )
    .Any();

我更喜欢后者,因为我发现它更具可读性,而且它引起的格式化问题更少,特别是在使用自动格式化时。当在单独的条件旁边(甚至上面)放置注释以澄清意图时,也会更清楚。

我的直觉告诉我第二个代码示例的效率会更低。当然,我可以自己编写一个简单的测试(如果没有人知道答案,我也会这么做)。现在我认为这是完美的食物。; p

  1. 一个比另一个更有效率吗?
  2. 编译器是否足够智能来优化这个?

编译器是否连接LINQ where查询?

编译器不尝试优化连续的"where"调用。运行库有。如果你有一大堆"where"answers"select"调用,运行时将尝试将它们重新组织成更有效的形式。

在一些不寻常的情况下,"优化"当然会使事情变得更糟。我似乎记得Jon Skeet最近写了一篇关于这个的文章,尽管我不确定它在哪里。

编译器不允许优化这个,因为它不知道Where()做什么。例如,您可能重载了Where(),并使用记录其结果的版本。(抖动可以做优化,但在实践中不太可能)

效率差异不太可能显著。你可以分析你的应用程序,看看它是否重要。

Update:显然抖动在这里执行优化。请看Eric Lippert的回答

我不认为这里有什么显著的区别。然而,如果你强制枚举集合,那么我希望有更大的差异

bool validFactory   = fields
    .Where( field => field.FieldType == typeof( DependencyPropertyFactory<T> ) )
    .ToList()
    .Where( field => field.IsStatic )     
    .ToList()
    .Any(); 

在您的两个原始代码示例中,我看到相同的执行-第一个项目检查FieldType,然后检查IsStatic,如果它存在,则返回true。否则选中第二项,依此类推。不需要解析整个集合

在上面的示例中,将独立于IsStatic检查为FieldType解析整个集合。这可能会降低效率。注意,这在您的代码片段中都是不必要的。