我们知道Linq是建立在匿名对象,Lamda表达式,拓展方法,对象初始化器等技术上的..........
那么通过一个简单的Select 拓展方法我来来看一看
static IEnumerable<TResult> Select<TResult>(this IEnumerable<TResult> Source,Function<TResult,TResult> Se){ foreach(var item in Source) { yield return Se(item); } }
我们可以看到拓展的对象是IEnumerable 接口对象,返回的也是IEnumerable,也正是它,才让我们能够在方法中
使用yield return xx 的语法,也正是yield的延迟加载造就了Linq的神奇
现在我们来看下例子,更加深入了解Linq的运行 过程
static double Squer(double d)//求一个数的平方 { Console.WriteLine("Computing Squer: " + d); return Math.Pow(d, 2); }
double[] d = { 1, 2, 3 }; var result = from b in d select Squer(b); Console.WriteLine("第一次"); foreach (var item in result) { Console.WriteLine(item); }
运行程序查看效果
好像和预料中的没有什么区别!!当我们把鼠标放到result变量上时就可以看到
那么按照常理来说,item不就应该只是结果吗?那为什么会输出,Computing Squer: x 这些呢?
这正是yield的神奇之处,我们在来看一个例子
static IEnumerable<int> dd() { Console.WriteLine("One....."); yield return 1; Console.WriteLine("Two....."); yield return 2; Console.WriteLine("Three....."); yield return 3; }
foreach (var item in dd()) { Console.WriteLine(item); }
这就说明了yield在内存中有个状态
那如果我把每个元素都改变了在遍历呢?
Console.WriteLine("每个加2,在查询"); for (int i = 0; i < d.Length; i++) { d[i] = d[i] + 2; } Console.WriteLine("第二次....."); foreach (var item in result) { Console.WriteLine(item); }
那我们也就知道了它自动获取到了要查询的值,那么我们怎么样才能马上得到值呢?而不是延迟的....,看下面代码
foreach (var item in result.ToList()) { Console.WriteLine(item); }
只是加了一个ToList()我们就可以看到结果发生了变化,根据前面说的,其实result早就知道自己是什么类型的结果集了,那么我就先运行,然后只把结果
保存在集合里面,那么就会出现上面的情况
下面在加上常用的查询操作符