c# - LINQ查询优化: specifically, let子句的位置重要吗?

标签 c# .net linq

我对 LINQ 表达式的编译和优化以及是否需要仔细考虑表达式中 let 和 where 子句的顺序感兴趣。

这里是示例:

var query = 
    from record in Database.Table
    let recordName = record.GetName()
    let notUsed = UselessData()
    let stuff = DoSomethingIntensiveWith(record)
    where recordName == "foobar"
    select stuff;

foreach (string item in query) {
    Console.WriteLine("item => '{0}'", item);
}

问题/假设:

  • record.GetName() 必须解析才能执行 where 条款。
  • notUsed 从未在表达式中使用,因此将调用 UselessData() 完全吗?
  • 仅当 recordName 等于“foobar”时才需要
  • stuff。将要 DoSomethingIntentialWith() 对每条记录或仅记录执行 其中 recordName 等于“foobar”?

如果我想确保仅在以下情况下调用 DoSomethingIntentialWith() recordName 等于“foobar”,我是否需要将 let caluse 放置在 where子句,如下:

var query = 
    from record in Database.Table
    let recordName = record.GetName()
    let notUsed = UselessData()
    where recordName == "foobar"
    let stuff = DoSomethingIntensiveWith(record)
    select stuff;

foreach (string item in query) {
    Console.WriteLine("item => '{0}'", item);
}

与此同时,我将使用一些真实的代码和调试器。患病的 报告我的发现。

最佳答案

如果这是 LINQ-to-Objects,那么:是的,您知道。标准 Enumerable.* 实现在按顺序应用事物方面非常直接。您不一定需要所有 let 子句,但事情仍然按顺序完成,并且该顺序受到尊重。如果它是 LINQ-to-anything-else,那么一切都失败了。

这很容易演示:

using System;
using System.Linq;
class Foo
{
    public Foo(string value)
    {
        Value = value;
    }
    public string Value { get; private set; }
    public string Expensive()
    {
        Console.WriteLine(Value);
        return Value;
    }
    static void Main()
    {
        var foos = new[] {
            new Foo("abc"),
            new Foo("def")};
        Console.WriteLine("query1:");
        var query1 = (from obj in foos
                      let val = obj.Value
                      where val.StartsWith("a")
                      let result = obj.Expensive()
                      select result).ToArray();
        Console.WriteLine("query2:");
        var query2 = (from obj in foos
                      let val = obj.Value
                      let result = obj.Expensive()
                      where val.StartsWith("a")                      
                      select result).ToArray();    
    }
}

第一个查询过滤然后项目(因此它只对匹配记录执行昂贵的操作),而第二个查询计算两者的昂贵操作:

query1:
abc
query2:
abc
def

应该注意的是,let实际上只是通过Select实现的 - 它是从源数据到查询内部使用的匿名类型的投影。

关于c# - LINQ查询优化: specifically, let子句的位置重要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13231500/

相关文章:

c# - 如何正确等待调用 Dispatcher.Invoke 的多个线程在 WPF 应用程序中完成

c# - 部署 ClickOnce 应用程序时出错 - list 中的引用与下载的程序集的标识不匹配

c# - 如何简化 C# 中的代码?

c# - Environment.UserName 返回应用程序池名称而不是用户名

c# - 您能否将 'It' 匹配器对象存储为变量,而不是将其内联定义? (起订量)

C# - 在 Regex.Replace 中使用 matchTimeout 参数

c# - Linq Group By Into 附加参数

c# - 使用 Console.Write 字符串格式化

c# - 将一个 XML 文档转换为另一个 XML 文档

c# - Linq 查询首选项