这篇文章主要介绍了详解LINQ入门(中篇),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
前 言
在上篇中简单的分享了LINQ的基础概念及基础语法,如果没有阅读过上篇的朋友可以点击这里。感谢大家的支持,本篇我们将更进一步的学习LINQ的一些相关特性及应用方法。废话不多说,请往下阅读吧。
延迟加载
在上篇中简单的和大家提到了LINQ具有一个很有意思的特性那就是“延迟加载”(或“延迟计算”),什么是延迟加载呢?先看来自官方的描述:延迟执行意味着表达式的计算延迟,直到真正需要它的实现值为止。是不是觉得有点生涩难理解呢?按照我个人的理解通俗的讲就是,每当我们编写好一段LINQ表达式时,此时这个表达式所代表的序列变量仅仅只是一个代理,编译器在执行编译时根本就不鸟这段代码,检查完语法正确性后直接跳过,直到代码在编译器动态运行序列变量在其他代码块被调用时,它所代理的linq表达式才会执行。啊~~看到这里你是不是要晕了,到底要怎么理解啊,无废话上代码:
// 已知一个序列
var array = new int[] {1, 2, 3};
// 编写一段LINQ表达式获得一个序列变量query
// 注意,这个变量仅仅是一个代理,在执行编译的时候,编译器检查完
// 该代码的正确性后直接跳过,不再理会
var query = from arr in array
where arr > 1
select arr;
// 调用上述序列变量query,此时上述的LINQ表达才会执行。注意此时已是在
// 编译器Runtime 的情况下执行
foreach(var q in query)
Console.WriteLine(q.ToString());
如果你觉得上述例子不能让你有个深刻的理解,那么请看来自MSDN的例子
public static class LocalExtensions
{
public static IEnumerable<string>
ConvertCollectionToUpperCase(this IEnumerable<string> source)
{
foreach (string str in source)
{
Console.WriteLine("ToUpper: source {0}", str);
yield return str.ToUpper();
}
}
}
class Program
{
static void Main(string[] args)
{
string[] stringArray = { "abc", "def", "ghi" };
// 这里方法 ConvertCollectionToUpperCase 是不会在编译时进行调用核查的,直到下面的foreach调用变量 q 此方法才会执行
var q = from str in stringArray.ConvertCollectionToUpperCase()
select str;
foreach (string str in q)
Console.WriteLine("Main: str {0}", str);
}
}
注意,ConvertCollectionToUpperCase 是一个静态扩展方法,后续讲解,如果你对.net 2.0 的 yeild 不熟悉的网上查阅吧,这里就不做介绍了。
// 输出结果
// ToUpper: source abc
// Main: str ABC
// ToUpper: source def
// Main: str DEF
// ToUpper: source ghi
// Main: str GHI
小结,延迟加载有好也有坏,由于是在Runtime的情况下执行序列,所以就容易造成未知异常,断点打错等等,所以编码LINQ是一定要考虑到它的这个特性。
lambda 表达式
了解完延迟加载后,那么现在我们需要简单的学习一下.net 3.5 给我们带来的新特性lambda表达式,在上篇的评论中,有园友问lambda和linq有什么关系,在这里其实他们没有任何关系,是完全不同的东西,但是我们为什么要掌握它呢?因为在后续的学习中会使用大量的lambda表达,他可以使我们的代码更优雅更有可读性,大大提高了我们的编码效率。
那么在学习lambda之前,先来回顾一下.net 2.0给我们带来的委托 delegate ,这个你一定不会感到陌生吧,而且一定会常用他。对于委托这里就不做详细的介绍了,要复习委托的在网上查阅吧。通过委托,我们可以得到一个东西“匿名方法”。咦,是不是觉得很眼熟,呵呵,用代码来加深回忆吧
public delegate void SomeDelegate1;
public delegate void SomeDelegate2(arg 1, arg 2);
// 匿名方法
SomeDelegate1 del1 += delegate() {...};
SomeDelegate2 del2 += delegate(arg1, arg2) {...}
上面的代码中我们看到在.net 2.0时代,我们可以通过delegate创建匿名方法,提高编码的灵活性,那么lambda和这个有什么关系呢,lambda对匿名方法进行了升华。看代码:
public delegate void SomeDelegate1;
public delegate void SomeDelegate2(arg 1, arg 2);
// 匿名方法
SomeDelegate1 del1 += () => {...};
SomeDelegate2 del2 += (arg1, arg2) => {...}
呵呵,是不是觉得有点不可思议呢,言归正传什么是lambda表达式呢,来自官方的定义:“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。 该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。 Lambda 表达式 x => x * x 读作“x goes to x times x”。在定义里提到了表达式树,这是高阶晋级的话题,这里就不做讨论了,我们先把精力放在入门与实战应用上。
常规的lambda表达式如下:
(parameters) => { }
当指定的委托类型没有参数是表达式可以如下
() => { } 例:() => {/*执行某些方法*
本文标题为:详解LINQ入门(中篇)
基础教程推荐
- C#类和结构详解 2023-05-30
- C#控制台实现飞行棋小游戏 2023-04-22
- unity实现动态排行榜 2023-04-27
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- C# windows语音识别与朗读实例 2023-04-27
- C# 调用WebService的方法 2023-03-09
- C# List实现行转列的通用方案 2022-11-02
- winform把Office转成PDF文件 2023-06-14
- ZooKeeper的安装及部署教程 2023-01-22
- 一个读写csv文件的C#类 2022-11-06