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

C# 编译器是否连接LINQ where查询?,c#,.net,linq,compilation,C#,.net,Linq,Compilation,考虑以下两个类似的代码示例 一个where子句 bool validFactory = fields .Where( fields => field.FieldType == typeof( DependencyPropertyFactory<T> ) && field.IsStatic ) .Any(); 我更喜欢第二种,因为我发现它更具可读性,而且格式问题更少,特别是在使用自动格式时。在单独条

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

一个
where
子句

bool validFactory
  = fields
    .Where(
      fields => field.FieldType == typeof( DependencyPropertyFactory<T> ) &&
                field.IsStatic )
    .Any();
我更喜欢第二种,因为我发现它更具可读性,而且格式问题更少,特别是在使用自动格式时。在单独条件(或甚至以上)旁边放置注释以澄清意图时,也更为清晰

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

  • 一个比另一个更有效率吗
  • 编译器是否足够聪明来优化这个问题

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

    效率差异不大可能很大。您可以分析您的应用程序,看看它是否重要


    更新:显然抖动在这里执行优化。请看埃里克·利珀特的答案。

    我不认为这里会有显著差异。然而,如果您强制枚举集合,那么我希望会有更多的差异

    bool validFactory   = fields
        .Where( field => field.FieldType == typeof( DependencyPropertyFactory<T> ) )
        .ToList()
        .Where( field => field.IsStatic )     
        .ToList()
        .Any(); 
    
    bool validFactory=字段
    .Where(field=>field.FieldType==typeof(DependencyPropertyFactory))
    托利斯先生()
    .Where(field=>field.IsStatic)
    托利斯先生()
    .Any();
    
    在您的两个原始代码示例中,我看到了相同的执行情况—第一项检查了
    FieldType
    ,然后检查了
    IsStatic
    ,如果它存在,则返回true。否则将选中第二项,依此类推。不需要解析整个集合

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

    编译器不会尝试优化连续的“where”调用运行库会这样做。如果有一大堆“where”和“select”调用同时出现,运行库将尝试将它们重新组织为更有效的形式


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

    似乎是重复的,但因为我也不知道如何搜索早期的问题……高度相关:当你谈论运行时时,你是在谈论像EF或L2S这样的ORM,还是CLR?因为我希望它们会生成相同的SQL查询,但是在LINQtoObjects中,我希望不会发生优化@盖布:我说的是林克对物体。您对不会发生优化的期望与现实不符,因此我给您的建议是调整您的期望。我们只是在争论“运行时”一词的定义吗?对我来说,“运行时”是指CLR,据我所知,它与CLR无关。当编译器选择
    Enumerable.WhereEnumerableIterator.Where
    作为第二个
    Where
    函数而不是
    Enumerable.Where
    时,就会发生优化。我认为库或编译器(可能两者都)负责优化,而不是运行时。@Gabe:对我来说,“运行时”是指任何在运行时工作的组件。在这种情况下,是库具有优化智能;LINQ to对象库中Where的实现执行优化;它知道它的参数何时是另一个Where或Select查询。这里优化的不是抖动,而是Where语句背后的代码。返回的IEnumerable在技术上是延迟计算的,因此在您请求第一个元素时,两个where子句都已生成,内部子句可以延迟地与外部子句组合。这与jitterAlso的任何巧妙之处不同,在使用C#4.0的“select”、“where”和“from”关键字(在内部转换为这些调用)的情况下,编译器可以知道在何处组合调用的语义,尽管我很确定Visual Studio one目前没有执行这种优化。
    bool validFactory   = fields
        .Where( field => field.FieldType == typeof( DependencyPropertyFactory<T> ) )
        .ToList()
        .Where( field => field.IsStatic )     
        .ToList()
        .Any();