当前位置 : 主页 > 网络安全 > 测试自动化 >

LINQ性能

来源:互联网 收集:自由互联 发布时间:2021-06-22
在针对对象集合的LINQ查询中幕后发生了什么?它只是语法糖或是否还有其他事情使它更有效的查询? 你的意思是查询表达式,或者查询在幕后做什么? 查询表达式首先扩展为“普通”
在针对对象集合的LINQ查询中幕后发生了什么?它只是语法糖或是否还有其他事情使它更有效的查询? 你的意思是查询表达式,或者查询在幕后做什么?

查询表达式首先扩展为“普通”C#.例如:

var query = from x in source
            where x.Name == "Fred"
            select x.Age;

被翻译成:

var query = source.Where(x => x.Name == "Fred")
                  .Select(x => x.Age);

这个的确切含义取决于当然的源类型……在LINQ to Objects中,它通常实现IEnumerable< T>.并且Enumerable扩展方法发挥作用……但它可能是一组不同的扩展方法. (例如,LINQ to SQL将使用Queryable扩展方法.)

现在,假设我们正在使用LINQ to Objects …在扩展方法扩展之后,上面的代码变为:

var query = Enumerable.Select(Enumerable.Where(source, x => x.Name == "Fred"),
                              x => x.Age);

接下来,Select和Where的实现变得很重要.抛出错误检查,它们是这样的:

public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
                                      Func<T, bool> predicate)
{
    foreach (T element in source)
    {
        if (predicate(element))
        {
            yield return element;
        }
    }
}

public static IEnumerable<TResult> Select<TSource, TResult>
    (this IEnumerable<TSource> source,
     Func<TSource, TResult> selector)
{
    foreach (TSource element in source)
    {
        yield return selector(element);
    }
}

接下来是迭代器块扩展到状态机,我不会进入这里,但我有一个article about.

最后,将lambda表达式转换为适当的委托实例创建(或表达式树,取决于所调用方法的签名)的额外方法.

所以基本上LINQ使用了很多C#的聪明功能:

> Lambda表达式转换(进入委托实例和表达式树)
>扩展方法
>通用方法的类型推断
>迭代器块
>通常是匿名类型(用于投影)
>通常是局部变量的隐式类型
>查询表达式翻译

但是,单个操作非常简单 – 它们不执行索引等.连接和分组是使用哈希表完成的,但像“where”这样的简单查询只是线性的.不要忘记LINQ to Objects通常只将数据视为只能向前发送的序列 – 它不能像二进制搜索那样执行.

通常我希望手写查询比LINQ to Objects快一点,因为抽象层次较少,但它们的可读性较差,性能差异通常不会很大.

与性能问题一样:如有疑问,请测量!

网友评论