编译器是否将LINQ连接到哪里查询?

时间:2011-09-11 23:16:33

标签: c# .net linq compilation

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

一个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();

我更喜欢第二种,因为我发现它更具可读性并且导致更少的格式化问题,尤其是在使用自动格式化时。在单独条件(或甚至上面)旁边放置注释以澄清意图时,也更清楚。

我的直觉说第二个代码示例的效率会降低。我当然可以自己写一个简单的测试(并且如果没人知道答案的话)。现在我认为这是SO的完美食物。 ; P

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

3 个答案:

答案 0 :(得分:12)

编译器不会尝试优化连续的“where”调用。 运行时库可以。如果你有一大堆“where”和“select”调用彼此相邻,运行时将尝试将它们重新组织成一种更有效的形式。

在一些不寻常的情况下,当然“优化”会让事情变得更糟。我似乎记得Jon Skeet最近写了一篇关于这篇文章的文章,虽然我不知道它在哪里。

答案 1 :(得分:4)

不允许编译器优化它,因为它不知道Where()的作用。例如,您可能已经使用记录其结果的版本重载了Where()。 (抖动可以进行优化,但实际上不太可能。)

效率差异不太可能显着。您可以对应用程序进行概要分析,看它是否重要。

更新:显然,抖动 在这里执行优化。见Eric Lippert的回答。

答案 2 :(得分:1)

我不希望这里有显着差异。但是,如果您强制枚举该集合,那么我会期待更多的差异

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

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

在上面的示例中,整个集合的解析将FieldType独立于IsStatic检查。这可能效率较低。请注意,在您的任何一个代码段中都不需要这样做。