Linq“.NET技术”学习笔记

简介:   写在前面  其实在09年就已经学习过Linq了,并被她那优美的语法所吸引,只是现在所在的公司还在使用VS2005在.Net2.0的框架下面的开发,所以Linq也很久没有用过了,最近看部门的同事对这个有些兴趣,所以打算整理点东西出来跟大家一起做个分享。

  写在前面

  其实在09年就已经学习过Linq了,并被她那优美的语法所吸引,只是现在所在的公司还在使用VS2005在.Net2.0的框架下面的开发,所以Linq也很久没有用过了,最近看部门的同事对这个有些兴趣,所以打算整理点东西出来跟大家一起做个分享。

  什么是Linq

  LINQ是Language Integrated Query的简称,它是集成在.NET编程语言中的一种特性。已成为编程语言的一个组成部分,在编写程序时可以得到很好的编译时语法检查,丰富的元数据,智能感知、静态类型等强类型语言的好处。并且它同时还使得查询可以方便地对内存中的信息进行查询而不仅仅只是外部数据源。

  Linq包括Linq to Objects, Linq to SQL,Linq to XML, Linq to DataSet等,本篇从Linq to Objects开始了解Linq的皮毛。

  开始Linq前你要知道的

  扩展方法

  顾名思义就是对现有类进行扩展的的方法,扩展方法可以在不修改现有类的情况下,为现有类增加公共的接口(不是C#中的interface)。

  扩展方法本质上是一个静态方法,不同之处在于它的第一个参数必须有this关键字声明,并且第一个参数的类型即为要扩展的类型。如

public static double ToDouble(this string source)
{
    double res = 0d;
    double.TryParse(source, out res);
    return res;
}
public static void SimpleExtesionMethod()
{
    double d = "12345.54321".ToDouble();
    Console.WriteLine(d);
}

  这里是个简单的将字符串转为double类型的扩展方法,只要引用了该方法的命名空间,则都可以直接用string类型来调用ToDouble方法。

  扩展方法是后文的基础,C#3.0中的Linq的实现都是基于扩展方法,通过对IEnumerable<T>接口(Linq to Objects)的扩展和对IQueryable<T>的扩展来实现Linq的相关功能,而Linq的相关关键字最终都是转化为对IEnumerable<T>(IQueryable<T>)的调用。

  Lambda表达式

  lambda表达式其实就是.net2.0中的匿名方法,然后再3.0中以一种更优美的姿态呈现出来。

  lambda表达式的基本语法为

  (参数列表) =>{语句块;}    或者

  ( 参数列表) =>表达式

  当参数列表中只有一个参数的时候,圆括号可以省略

Func<string, string> func = x => x + x;
Console.WriteLine(func("a")); 

  Var:隐式类型化变量

  使用与可以由编译器推导出的变量的声明,不需要显式指定对象的类型。

var container = new List<string> { "张三", "李四", "王五" };
IEnumerable<string> query = from name in container
            select name;

  上例中由于定义中已经指明了对象的类型,声明中已经完全没有必要使用显示的类型定义,所以可以使用var关键字。

  对于匿名对象

var test = new { Name = "Sth.", Type = "UnKnown" };

  由于无法用一个类型类声明匿名对象,此时可以用var是声明。

  注意var只是省下了显式声明的过程,而C#本身就是静态语言,所以var所声明的变量的类型已经确定任然是不能改变的,亦即,var并非是变体类型。

  Linq对谁适用

  linq的语法通过System.Linq下面的Enumerable类提供支持,通过观察他的签名,你就会发现他为IEnumerable<T>实现了一系列的扩展方法,也就是说,只要是实现了IEnumerable<T>的对象都可以使用Linq的语法来查询。

  而对于只实现了IEnumerable接口而没有实现IEnumerable<T>的对象可以通过

 
 
public static IEnumerable < TResult > Cast < TResult > ( this IEnumerable source);

  来将IEnumerable接口转为IEnumerable<T>(例如ArrayList)。

  Linq中的关键字

  在C#3.0中,为Linq引入了一些新的关键字,他们是:

  from join where group into let orderby select

  熟悉Sql的同学看着是不是有些眼熟呢,其实在Linq中他们的涵义和在SQL中类似的,所以会很容易理解的。接下来的时间,简单介绍下这些关键字的使用。

  from

  from子句是一个Linq查询的开始,任何一个Linq语句都是以from开始,from子句指定查询的容器,和在此语句有效的局部变量(用来指定容器中的一项,from子句的效果很类似于foreach)。from子句的语法为

 from local in container上海企业网站设计与制作pre>

  local就是在此Linq语句中的局部变量,由于container必须为IEnumerable<T>,他的类型可以由container推导出来(即T)。上一段简单的例子:

var container = new List<string> { "张三", "李四", "王五" };
var query = from name in container
            select name;
foreach (string name in query)
{
    Console.WriteLine(name);
}

  输出

张三
李四
王五

  如果container仅仅实现IEnumerable而没有实现IEnumerable<T>,则需要显式指定局部变量的类型,或者是使用Cast转为IEnumerable<T>

var container = new ArrayList { "张三", "李四", "王五" };
var query = from name in container.Cast<string>()
            select name;
//或者
var query1 = from string name in container
             select name;

  select

  对查询的结果进行投影,在子句中指定要选择的列,如上例。

  有的时候,我们只需要投影某一列,我们可以这样

private static void TestSelectSingleProperty()
{
    var persons = GetPersons();
    var query = from p in persons
                select p.Name;
    foreach (var item in query)
    {
        Console.WriteLine(item);
    }
}

  我们还可以指定要投影的列的集合,这个时候我们要用到匿名类型

var query = from p in persons
            select new { p.ID, p.Name };
foreach (var item in query)
{
    Console.WriteLine("No:{0},Name:{1}",item.ID,item.Name);
}

  query中的每一项都时候一个拥有ID属性和Name属性的对象,当然有的时候实体的属性名不是我们想要的,或者是通过对属性计算得来的,那么我们可以显式指定属性名,就像下面这样:

var query = from p in persons
            select new
            {
                UserID = p.ID,
                FriendName = p.Gender == "男" ? "Mr" : "Ms" + p.Name
            };
foreach (var item in query)
{
    Console.WriteLine("No:{0},Friendly Name:{1}", item.UserID, item.FriendName);
}

  where

  对容器内的数据进行筛选。

var query = from p in persons
            where p.DepartmentID == 1
            select p.Name;

  join

  类似SQL里的join,Linq中的join子句用于将两个容器的数据以某种关系进行关联。

var departments = GetDepartments();
var persons = GetPersons();
var query = from d in departments
            join p in persons on d.ID equals p.DepartmentID
            select new { d, p };

  值得注意的是join子句只能使用equals或者是not equal而不能用其他运算符(==都不行)。而equals运算符左边必须联接的左部,右边为右部,不能调换的,否则编译不能通过。

  into

  into子句用于将join或者是group子句的结果进一步持续化,包装成为一个

  System.Linq.IGrouping<TKey, TElement>

  对象,而且IGrouping继承自IEnumerable<TElement>,可以看出,IGrouping接口提供分组的键和,该键下所包含的集合。例子见group

  group

  对结果按照指定的条件进行分组

var container = new List<string> { "ZhangSan", "LiSi", "Wangwu", "ZhaoLiu", "Deng" };
var query = from name in container
            group name by name.Length into g
            select new { g.Key, Values = g };

  例子演示了通过姓名的长度对一个姓名列表进行分组,并将分组的结果保持到局部变量g中,可以通过下面的代码将query的结果输出

foreach (var group in query)
{
    Console.WriteLine("{0}:", group.Key);
    上海企业网站制作 style="color: blue;">foreach (var item in group.Values)
    {
        Console.WriteLine(item);
    }
} 

  let

  let子句用于在查询中添加一个新的局部变量,使其在后面的查询中可见

var query = from p in persons
            let friendlyName = p.Gender == "男" ? "Mr" : "Ms" + p.Name
            select new
            {
                UserID = p.ID,
                FriendName = friendlyName
            };
foreach (var item in query)
{
    Console.WriteLine("No:{0},Friendly Name:{1}", item.UserID, item.FriendName);
}

  在IEnumerable<T>上的其他扩展

  Take Skip

  用于选取前XX个或者和跳过前XX个,如选择第11到20个则可以

query.Skip(10).Take(10);

  OrderBy OrderByDescending

  排序而已

query.OrderBy(c => c.Length);

  Distinct Union Intersect Except 这些单词都见过吧,分别就是取不重复,并集,交集,差集(这个貌似看看参数就明白了)

  其他扩展都在Enumerable类下面了。

  Linq的延迟加载特性

  Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的。从而使Linq查询只是在需要的时候才会被执行。

  但是,某一些扩展方法在执行时会试图遍历整个容器,从而使延迟加载无效,如排序,聚合函数(Count,Sum,Average等。)

static IEnumerable<int> InfinityInts()
{
    int count = 0;
    while 上海网站建设(true)
        yield return count++;
}
public static void LazyLoad()
{
    var query = from i in InfinityInts()
                select i;
    foreach (var i in query.Take(20))
    {
        Console.WriteLine(i);
    }
}
public static void CantDoLazyLoad()
{
    var query = from i in InfinityInts()
                select i;
    foreach (var i in query.OrderBy(i => i).Take(20))
    {
        Console.WriteLine(i);
    }
}

  这里有个简单的例子来证明,当使用Take时候,Linq语句能正常的执行,而当我们再Linq上使用一个Order By之后,程序就卡死了,当然,这是理所应当的,在失去延迟加载的特性之后,试图对一个无穷序列排序的结果一定是outOfMemory。

  最后

  这都只是皮毛,感兴趣的同学可以自己去MSDN查看更详细的资料,最后,推荐一个工具和一个网站:

  LINQPAd(http://www.linqpad.net/)  一个非常有用的Linq学习工具

  Linq 101 微软官方的Linq样例代码

目录
相关文章
|
3月前
|
人工智能 前端开发 Devops
.NET技术在现代开发中的作用:.NET技术的核心价值、在现代应用开发中的实际应用、以及面临的挑战与未来趋势。
.NET技术是软件开发领域的核心力量,本文从其核心价值、实际应用及未来挑战三方面进行探讨。它支持多种语言,提供强大的开发工具和丰富的类库,并具备跨平台能力。在现代应用开发中,.NET广泛应用于企业级系统、Web应用、移动应用、云服务和游戏开发等领域。面对性能优化、容器化、AI集成等挑战,.NET持续创新以适应不断发展变化的技术环境。
60 4
|
3月前
|
人工智能 开发框架 .NET
.NET技术的强大功能:.NET技术的基础特性、在现代开发中的应用、以及它如何助力未来的软件开发。
.NET技术是软件开发领域的核心支柱,以其强大功能、灵活性及安全性广受认可。本文分三部分解析:基础特性如多语言支持、统一运行时环境;现代应用如企业级与Web开发、移动应用、云服务及游戏开发;以及未来趋势如性能优化、容器化、AI集成等,展望.NET在不断变化的技术环境中持续发展与创新。
115 4
|
3月前
|
人工智能 物联网 开发者
.NET技术在现代软件开发中的应用愈发广泛和深入
.NET技术是软件开发的关键支柱,本文分为三部分探讨其创新应用:最新进展如.NET 5/6统一平台、性能提升、跨平台支持增强、云集成优化及开源社区贡献;应用场景涵盖微服务架构、物联网、AI/机器学习、游戏及移动应用开发;未来发展潜力在于持续性能优化、云原生支持、新兴技术集成、生态扩张及教育培训加强。.NET正以其强大适应性和创新潜力引领软件开发的新方向。
47 3
|
3月前
|
人工智能 开发框架 .NET
如何掌握.NET技术,引领开发前沿:.NET技术的核心能力、在现代开发中的应用实践、以及如何通过.NET技术实现持续创新。
.NET技术已成为软件开发不可或缺的部分,本文分三部分探讨:核心能力如多语言支持、统一运行时环境、丰富的类库及跨平台能力;现代开发实践包括企业级应用、Web与移动开发、云服务及游戏开发;并通过性能优化、容器化、AI集成等方面实现持续创新,使开发者站在技术前沿。
63 3
|
28天前
|
人工智能 开发框架 C#
C#/.NET/.NET Core技术前沿周刊 | 第 6 期(2024年9.16-9.22)
C#/.NET/.NET Core技术前沿周刊 | 第 6 期(2024年9.16-9.22)
|
27天前
|
人工智能 开发框架 Cloud Native
C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)
C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)
|
27天前
|
数据可视化 NoSQL C#
C#/.NET/.NET Core技术前沿周刊 | 第 8 期(2024年10.01-10.06)
C#/.NET/.NET Core技术前沿周刊 | 第 8 期(2024年10.01-10.06)
|
28天前
|
开发框架 .NET 开发工具
.NET 9 中 LINQ 新增的功能
.NET 9 中 LINQ 新增的功能
|
28天前
|
设计模式 开发框架 C#
C#/.NET/.NET Core技术前沿周刊 | 第 4 期(2024年9.1-9.8)
C#/.NET/.NET Core技术前沿周刊 | 第 4 期(2024年9.1-9.8)
|
2月前
|
人工智能 前端开发 开发工具
解读.NET 技术的开发潜力
本文全面介绍了.NET技术在软件开发领域的核心优势、创新应用及面临的挑战。.NET以其统一的开发平台、强大的工具和跨平台能力,成为企业级应用、Web应用乃至游戏开发的理想选择。然而,在性能优化、容器化及AI集成等方面仍需不断突破。通过积极拥抱开源和社区驱动模式,.NET将持续推动软件开发的进步。
55 1
下一篇
无影云桌面