在针对对象集合的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快一点,因为抽象层次较少,但它们的可读性较差,性能差异通常不会很大.
与性能问题一样:如有疑问,请测量!