C#编程语言非常优美,我个人还是非常赞同的。特别是在学习一段时间C#后发现确实在它的语法和美观度来说确实要比其它编程语言强一些(也可能是由于VS编译器的加持)用起来非常舒服,而且对于C#我觉得他最优美之处不仅仅是语法糖方面还有就是体现在LINQ和Lambda表达式。

本篇文简单介绍一下关于C#当中LINQ表达式和其对应的Lambda表达式的用法,关于这两部分内容的相关参考资料:

人民邮电出版社《C#程序设计及应用教程》(第3版)

博客园博客:《c# Linq查询

同时在介绍的时候我会尽量挑出重要部分同时加上我自己的理解和认识,如有偏差还请指教。

首先先让我们看一下什么是LINQ查询表达式和Lambda表达式:

运行结果:

以上是对LINQ查询表达式和Lambda表达式的一个简单的应用,都是查询stu列表中年龄大于等于20岁的结果并且把结果按照年龄降序排列。

由此可见Linq表达式和Lambda表达式并没有什么可比性,只是用Lambda可以实现LINQ的查询语句。

那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在《深入理解C#》中称其为“点标记”。

例子中主要以LINQ表达式为主,LINQ表达式结构更为清晰易于理解,同时也会给出对应的点标记写法(所有的LINQ查询表达式都可以转成对应的点标记。反之,不是所有的点标记都可以转成查询表达式。),所以如果想要了解这部分的读者也请往下看。本文会介绍LINQ查询表达式用法以及对应的Lambda表达式。

LINQ查询表达式是一组查询技术的统称,其主要思想是将各种查询功能直接集成到C#语言中,不论是对象、XML、还是数据库都可以用LINQ编写查询语句。LINQ与传统迭代技术实现的查询优势在于更简明、更易读这种优势特别是在筛选多个条件时更为显著;使用很少的程序代码便能实现复杂的查询和筛选;无需修改或者是进行很少的修改就能移植到其它的数据源。LINQ查询语句并不复杂并且与SQL语句有些类似,学习起来难度并不大。

接下来直接看LINQ查询例子:

 //以下为例子中涉及查询的数据
List<Student> stu = new List<Student>()
3 {
  new Student(){Id = ,Name = "王同学",Age = },
  new Student(){Id = ,Name = "王同学",Age = },
  new Student(){Id = ,Name = "王同学",Age = },
  new Student(){Id = ,Name = "赵同学",Age = },
  new Student(){Id = ,Name = "钱同学",Age = },
  new Student(){Id = ,Name = "孙同学",Age = },
  new Student(){Id = ,Name = "周同学",Age = },
11   new Student(){Id = ,Name = "吴同学",Age = },
  new Student(){Id = ,Name = "郑同学",Age = },
  new Student(){Id = ,Name = "蒋同学",Age = }
};

查询年龄是30岁的王同学的信息:

 //查询年龄是30岁的王同学的信息
var res = from t in stu
where t.Name == "王同学" && t.Age ==
select t; //对应的Lambda表达式
//var res1 = stu.Where(t => t.Age == 30 && t.Name == "王同学"); foreach (var item in res)//显示查询结果
{
Console.Write("学号:"+item.Id+"\n姓名:"+item.Name+"\n年龄:"+item.Age);
}

运行结果:

LINQ查询表达式必须以form子句开头,并且必须以select或group子句结尾。在第一个from子句和最后一个select或group子句之间,查询表达式可以包含一个或者多个where、orderby、join、let甚至附加from子句。LINQ表达式整体的用法和SQL语句很像,在上面的例子中就可以看出。

上面的例子的含义就是从数据源stu中查询一个数据“t”,“t”满足的条件就是它的Name是王同学同时它的Age是30,然后查询这个“t”。LINQ查询语句的返回值类型为IEnumerable<T>,LINQ执行查询时,一般利用foreach循环执行查询得到一个序列,这这种方式称为“延迟执行”。

什么是“延迟执行”?还是上面例子中的查询:

 //查询年龄是30岁的王同学的信息
var res = from t in stu
where t.Name == "王同学" && t.Age ==
select t;
//var res1 = stu.Where(t => t.Age == 30 && t.Name == "王同学");Lambda表达式写法 foreach (var item in res)
{
Console.Write("学号:"+item.Id+"\n姓名:"+item.Name+"\n年龄:"+item.Age);
} Console.WriteLine("\n--------------------------------------------------------------------------"); stu.Add(new Student(){Id = ,Name = "王同学",Age = }); foreach (var item in res)
{
Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age);
Console.WriteLine();
}

运行结果:

延迟查询就是只需构造一次查询语句,可以多次使用。在List中添加新元素之后并没有重新执行查询操作,然而res中的结果却根据List中元素的改变相应发生了改变。

从学生中选出年龄小于25岁并且按照年龄降序排列

 //从学生中选出年龄小于25岁并且按照年龄降序排列
var res = from t in stu
where t.Age <
orderby t.Age descending
select t;
//var res1 = stu.Where(t => t.Age < 25).OrderByDescending(t => t.Age).Select(t => t);Lambda写法 foreach (var item in res)
{
Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age);
Console.WriteLine();
}

运行结果:

从学生中查询姓王的同学的信息并且按照年龄降序排列

 //从学生中查询姓王的同学的信息并且按照年龄降序排列
var res = from t in stu
from n in t.Name
where n == '王'//名字中带有王字
orderby t.Age descending
select t;
//var res1 = stu.Where(t => t.Name.IndexOf("王") == 0).OrderByDescending(t => t.Age);lambda表达式 foreach (var item in res)
{
Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age);
Console.WriteLine();
}

运行结果:

学生信息按照年龄、Id进行排序

 //参数越靠前,优先级越高
//先按age排序,当分数相同时再按id排序...依次类推 var res = from t in stu
orderby t.Age, t.Id
select t;
//var res1 = stu.OrderBy(t => t.Age).ThenBy(t => t.Id);Lambda表达式 foreach (var item in res)
{
Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age);
Console.WriteLine();
}

运行结果:

按照年龄进行分组,查询相同年龄数量大于2的内容

 //按照年龄进行分组,查询相同年龄数量大于2的内容
var res = from t in stu
group t by t.Age into s
where s.Count()>=
select s;
//var res1 = stu.GroupBy(t => t.Age).Where(s => s.Count() >= 2);lambda表达式 foreach (var item in res)
{
foreach (var items in item)
{
Console.Write("学号:" + items.Id + "\n姓名:" + items.Name + "\n年龄:" + items.Age);
Console.WriteLine();
}
Console.WriteLine();
}

运行结果:

查询出集合qSt中year等于集合qSc中year的元素并形成新的集合

 List<s> pSt = new List<s>();
pSt.Add(new s() { year = , name = "小张" });
pSt.Add(new s() { year = , name = "小王" });
pSt.Add(new s() { year = , name = "小李" });
pSt.Add(new s() { year = , name = "小赵" });
List<school> pSc = new List<school>();
pSc.Add(new school() { year = , name = "aaa" });
pSc.Add(new school() { year = , name = "bbb" });
pSc.Add(new school() { year = , name = "ccc" });
pSc.Add(new school() { year = , name = "ddd" });
pSc.Add(new school() { year = , name = "fff" }); var res = from t1 in pSc
from t2 in pSt
where t1.year == t2.year
select new {year = t1.year, name = t1.name + t2.name}; foreach (var item in res)
{
Console.Write("年:" + item.year + "姓名:" + item.name);
Console.WriteLine();
}

运行结果:

并行linq

并行查询可以分解查询的工作,使其分布在多个线程上。当pc拥有多个cpu时,可以看到并行查询带来的改进效果。并行LINQ适用于大型的集合查询,并拥有一定的优势。使用System.Collections.Concurrent.Partitioner.Create可以手动创建分区器。可以粗鲁的认为并行linq对于大集合的查询是优势比较明显的。取消长时间运行的并行linq查询可以设置利用System.Threading.CancellationTokenSource设置取消操作。

 Console.WriteLine("开始构造大数组...");
//构造大数组
const int count = ;
var data = new int[count];
var r = new Random();
for (int i = ; i < count; i++)
{
data[i] = r.Next();
}
Console.WriteLine("开始计算...");
var st = System.DateTime.Now;
var sum = (from x in data where x > select x).Sum();//常规linq-耗时1.8641s
var st2 = System.DateTime.Now;
var sum2 = (from x2 in data.AsParallel() where x2 > select x2).Sum();//并行查询-耗时0.6620s //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查询----x3 => x3 > 20(Lambda表达式)
var st3 = System.DateTime.Now; /*Partitioner.Create
手动创建分区器以及终止LINQ查询的方法可以详见文初的博客链接
Create具有多个重载,可依据需求进行分区*/ var sum4 = (from c in System.Collections.Concurrent.Partitioner.Create(data, true).AsParallel() where c > select c).Sum(); var dt1 = st2 - st;
var dt2 = st3 - st2;
Console.WriteLine("常规linq耗时:{0}s", dt1.TotalSeconds.ToString());
Console.WriteLine("并行linq耗时:{0}s", dt2.TotalSeconds.ToString());
Console.ReadKey();

运行结果:

写在最后,如果你对以上LINQ以及对应的Lambda的使用方法都已经了解那你已经初步了解了LINQ查询表达式和Lambda表达式,这里需要说明的一点是关于Lambda的使用方法并不仅仅只限于进行查询,他是一个主要用于简化委托的代码编写形式,他用法远比文中介绍的更加广泛,本文是为了对比展现LINQ和Lambda。

以上内容欢迎指正交流。

C# LINQ查询表达式用法对应Lambda表达式的更多相关文章

  1. C#在泛型类中,通过表达式树构造lambda表达式

    场景 最近对爬虫的数据库架构做调整,需要将数据迁移到MongoDB上去,需要重新实现一个针对MongoDB的Dao泛型类,好吧,动手开工,当实现删除操作的时候问题来了. 我们的删除操作定义如下:voi ...

  2. Linq To sql入门练习 Lambda表达式基础

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  3. Linq学习系列-----1.1 Lambda表达式介绍

     1.1  Lambda表达式介绍 下图就是一个典型的Lambda表达式. instance:输入参数 =>:Lambda操作符 instance.MemoryCount>=20*1024 ...

  4. Kotlin对象表达式要点与Lambda表达式

    Kotlin对象表达式要点揭密: 在上一次https://www.cnblogs.com/webor2006/p/11352421.html中学习了Kotlin的对象表达式,它主要是解决Java中匿名 ...

  5. 在Linq to Entity 中使用lambda表达式来实现Left Join和Join

    1.读取用户和部门两个表的左连接: var sg = db.Users.GroupJoin(db.Departments, u => u.DepartmentId, d => d.Depa ...

  6. 委托、 Lambda表达式和事件——Lambda表达式

    /* * 由SharpDevelop创建. * 用户: David Huang * 日期: 2015/7/30 * 时间: 16:32 */ using System; namespace Lambd ...

  7. C# Lambda表达式和linq表达式 之 匿名对象查询接收

    很多小伙伴都用过Lambda表达式和linq表达式,用起来也得心应手,但是有的小伙伴 对匿名对象的查询与接收比较迷茫,(没有定义相应的实体),怎么在where()里面进行 条件筛选呢?常规用法我就不说 ...

  8. Linq专题之Lambda表达式

    这一节我们讲的Lambda表达式跟匿名函数有关.Lambda表达式就是一个匿名函数,它可以包含表达式和语句,并且可以创建委托和表达式树. Lambda表达式的组成: 输入参数.Lambda运算符(=& ...

  9. lambda表达式查询经验:IN 和groupby的使用

    lambda In的用法: lambda表达式查询没有IN这个方法,可以变通一下,in查询的数组是否包含在映射对象里面的集合里: 如下代码: var departmentIDs = input.Dep ...

随机推荐

  1. 什么是神经网络 (Neural Network)

    反向传播: 可以看作是再一次将传过来的信号传回去, 看看这个负责传递信号神经元对于”讨糖”的动作到底有没有贡献, 让它好好反思与改正, 争取下次做出更好的贡献. 生物神经网络和人工神经网络的差别: 人 ...

  2. 【一起学源码-微服务】Nexflix Eureka 源码七:通过单元测试来Debug Eureka注册过程

    前言 上一讲eureka client是如何注册的,一直跟到源码发送http请求为止,当时看eureka client注册时如此费尽,光是找一个regiter的地方就找了半天,那么client端发送了 ...

  3. codefoces 22E 图论

    有些题还得练练模拟的能力呀 这题一言难尽,他给的 图不是半连通子图呀,我崩溃了 要分好组,然后1给2连,2给3连,.....n给1连.. 具体看代码,我写的比较捞了吧.. #include<io ...

  4. cocos2dx Vec2

    //SE是坐标重叠部分 // returns true if segment A-B intersects with segment C-D. S->E is the overlap part ...

  5. OpenVINO 入门

    关于OpenVINO 入门,今天给大家分享一个好东西和好消息! 现如今,说人工智能(AI)正在重塑我们的各行各业绝不虚假,深度学习神经网络的研究可谓如火如荼, 但这一流程却相当复杂,但对于初学者来说也 ...

  6. $CH0601\ Genius\ ACM$ 倍增优化DP

    ACWing Description 给定一个长度为N的数列A以及一个整数T.我们要把A分成若干段,使得每一段的'校验值'都不超过N.求最少需要分成几段. Sol 首先是校验值的求法: 要使得'每对数 ...

  7. 「CH2601」 电路维修 解题报告

    CH2601 电路维修 描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障 ...

  8. Jenkins2构建pipeline流水线

    流水线有两种方式: 1.脚本式流水线 2.声明式流水线 构建流水线的简单示例: 脚本式流水线 node ('master'){ stage("Source"){ //从Git仓库中 ...

  9. 为什么大家都说Java中只有值传递?

    最近跟Java中的值传递和引用传递杠上了,一度怀疑人生.查了很多资料,加上自己的理解,终于搞清楚了,什么是值传递和引用传递.也搞明白了,为什么大家都说Java只有值传递,没有引用传递.原来,我一直以来 ...

  10. JavaScript中函数式编程中文翻译

    JavaScript 中的函数式编程 原著由 Dan Mantyla 编写 近几年来,随着 Haskell.Scala.Clojure 等学院派原生支持函数式编程的偏门语言越来越受到关注,同时主流的 ...