C#进阶-LINQ表达式基础语法

简介: 本篇文章我们将演示LINQ扩展包的基础语法,以Select查询、Count计数、Average平均值、OrderBy排序函数为例,目前LINQ支持两种语法,我会在每个案例前先用大家熟知的SQL语句表达,再在后面用C#的两种LINQ语法分别实现。LINQ语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。

基础语法

在学习之前,我们要做一些准备工作,我们需要创建User对象和包含User对象的集合,作为后面查询和输出的数据源,参见这篇文章C#进阶之LINQ表达式总结完成准备工作。

数据源:


1、Select 查询

/* SQL里的表达: 查找用户里职业是医生的人的姓名,按照年龄倒序输出 */selectnamefromuserwhereoccupation="Doctor"orderbyagedesc;
/* C#版本1 */List<string>nameList= (fromuinlistwhereu.occupation=="Doctor"orderbyu.agedescendingselectu.name).ToList();
/* C#版本2 */List<string>nameList=list.OrderByDescending(u=>u.age).Where(p=>p.occupation=="Doctor").Select(x=>x.name).ToList();

LiuGuangzhi, LiuZiming, LiuShuai/* 输出结果 */

其中,C#版本1的语法是 from 变量名 in 集合 where 条件 orderby 条件 select 结果变量,得到的结果是LINQ的内置类型<Enumerable>,可直接视为匿名类型(var),需用.ToList()转换为List<string>类型。C#版本2是LINQ的一种扩展写法,是更加常用的写法。


2、Count 计数

/* SQL里的表达: 查找用户里姓Zhang的女性教师的数量*/selectcount(*) fromuserwhereoccupation="Teacher"andnamelike'Zhang%'andgender=false;
/* C#版本1 */intcount= (fromuinlistwhereu.occupation=="Teacher"where!u.genderwhereu.name.StartsWith("Zhang") selectu).Count();
/* C#版本2 */intcount=list.Count(u=>u.occupation=="Teacher"&&!u.gender&&u.name.StartsWith("Zhang"));

1/* 输出结果 */

3、Average 平均值

/* SQL里的表达: 查找用户里姓Liu的小于40岁的医生的平均年龄 */selectavg(age) fromuserwhereoccupation="Doctor"andnamelike'Liu%'andage<40;
/* C#版本1 */doubleaverageNum= (fromuinlistwhereu.occupation=="Doctor"whereu.age<40whereu.name.StartsWith("Liu") selectu.age).Average();
/* C#版本2 */doubleaverageNum=list.Where(u=>u.occupation=="Doctor"&&u.age<40&&u.name.StartsWith("Liu")).Select(u=>u.age).Average();

35/* 输出结果 */

4、Max/Min/Sum/ 最大/小值/总和

这里仅需参考LINQ求平均值的例子,求最大/小值或者总和时,只需要把C#语句末尾的.Average()方法替换成.Max()/.Min()/.Sum()即可。


5、OrderBy 排序

/* SQL里的表达: 查找用户里名字带Jin的人,优先按照年龄倒序,其次按照姓氏拼音正序,输出这些人的全部信息 */select*fromuserwherenamelike'%Jin%'orderbyagedescnameasc;
/* C#版本1 */List<User>userList= (fromuinlistwhereu.name.Contains("Jin") orderbyu.agedescendingorderbyu.nameselectu).ToList();
/* C#版本2 */List<User>userList=list.Where(u=>u.name.Contains("Jin")).OrderByDescending(u=>u.age).OrderBy(u=>u.name).ToList();

{id=10, name=HuJin, age=21, gender=False, occupation=Student}, 
{id=7, name=LiuJin, age=21, gender=True, occupation=Builder}, 
{id=2, name=ZhangJin, age=18, gender=False, occupation=Student} /* 输出

6、 Any/All 函数

Any()函数判断判断是否至少存在一个符合元素符合条件;All()函数判断是否全部元素都符合条件;下面以Any()函数为例:

/* SQL里的表达: 查找用户里是否存在年龄小于30岁职业是医生的女性 */selectcount(*) fromuserwhereoccupation="Doctor"andgender=falseandage<30; //返回符合的个数
/* C#版本1 */boolresult= (fromuinlistwhereu.age<30where!u.genderwhereu.occupation=="Doctor"selectu).Any();
/* C#版本2 */boolresult=list.Any(u=>u.age<30&&!u.gender&&u.occupation=="Doctor");

数据源中所有医生如下:

可以看到,目前我们数据源里是有Liu Shuai这一条符合三个属性(小于30岁/医生/女性)的。

true/* 输出结果 */

这里Any()函数是只要存在至少一个符合全部条件的结果,即返回布尔值True,只有在一个都不符合条件的情况下才会返回False;与之相反,All()函数只有在全部数据都符合全部条件的情况下,才会返回True,只要有一条不满足就返回False;All()函数的语法和Any()函数的语法相同,上面的例子把Any()直接替换成All()即可。


7、Single/SingleOrDefault 函数

Single()判断是否只有一个元素符合条件,若成立则返回该元素,若不成立则抛出异常。

/* SQL里的表达: 查找用户里年龄小于30岁职业是医生的女性 */select*fromuserwhereoccupation="Doctor"andgender=falseandage<30
/* C#版本1 */UseruserResult= (fromuinlistwhereu.age<30where!u.genderwhereu.occupation=="Doctor"selectu).Single();
/* C#版本2 */UseruserResult=list.Single(u=>u.age<30&&!u.gender&&u.occupation=="Doctor");

{id=6, name=LiuShuai, age=29, gender=False, occupation=Doctor} /* 输出结果 */

Single()要求有且只有一条满足要求的数据,多条满足条件或一条也没有,此方法会报错;

SingleOrDefault()要求最多有一条满足要求的数据,多条满足条件,此方法会报错;没有数据则返回数据类型的默认值;

类似的还有First()、FirstOrDefault()、Last()、LastOrDefault(),这里给大家做了一个异常表格记录了各种情况的返回值:

函数 没有满足 一条满足 多条满足 list本身为Null
Single 异常 该元素 异常 异常
SingleOrDefault 默认值 该元素 异常 异常
First 异常 该元素 第一个元素 异常
FirstOrDefault 默认值 该元素 第一个元素 异常
Last 异常 该元素 末尾的元素 异常
LastOrDefault 默认值 该元素 末尾的元素 异常

面对可能出现的异常,我们一般在使用这类方法时要进行Try{…}Catch(…){…}。


8、Skip/Take/Top 函数

/* SQL里的表达: 查找用户表自然排序第4个人到第6个人的姓名*/selectnamefromuserlimit3,3;
/* C#版本1 */List<string>nameList= (fromuinlistselectu.name).Skip(3).Take(3).ToList();
/* C#版本2 */List<string>nameList=list.Skip(3).Take(3).Select(x=>x.name).ToList();

LiuGuangzhi, LiuZiming, LiuShuai/* 输出结果 */

同理,Top(n)表示截取前n条数据。

目录
相关文章
|
3月前
|
开发框架 .NET 编译器
C# 10.0中Lambda表达式的改进:更简洁、更灵活的代码编写体验
【1月更文挑战第21天】随着C#语言的不断发展,Lambda表达式作为一种简洁、高效的函数式编程工具,在C# 10.0中迎来了重要的改进。本文将详细探讨C# 10.0中Lambda表达式的新特性,包括参数类型的推断增强、自然类型的Lambda参数以及Lambda表达式的属性改进等。这些改进不仅简化了Lambda表达式的编写过程,还提升了代码的可读性和灵活性,为开发者带来了更优质的编程体验。
|
3月前
|
存储 开发框架 .NET
【C#】C# 基础语法与游戏开发
【1月更文挑战第21天】【C#】C# 基础语法与游戏开发
|
1月前
|
开发框架 .NET C#
C#学习相关系列之Linq用法---where和select用法(二)
C#学习相关系列之Linq用法---where和select用法(二)
|
1月前
|
C#
C#语法快速热身
C#语法快速热身
7 0
|
1月前
|
开发框架 .NET C#
C#学习相关系列之Linq用法---group和join相关用法(三)
C#学习相关系列之Linq用法---group和join相关用法(三)
|
1月前
|
开发框架 .NET C#
C#学习相关系列之Linq常用方法---排序(一)
C#学习相关系列之Linq常用方法---排序(一)
|
1月前
|
开发框架 .NET 编译器
C#学习相关系列之匿名方法和Lambda表达式
C#学习相关系列之匿名方法和Lambda表达式
|
1月前
|
存储 C# 开发者
C#基础语法
C#基础语法
11 0
|
1月前
|
开发框架 安全 .NET
C# .NET面试系列三:集合、异常、泛型、LINQ、委托、EF!
<h2>集合、异常、泛型、LINQ、委托、EF! #### 1. IList 接口与 List 的区别是什么? IList 接口和 List 类是C#中集合的两个相关但不同的概念。下面是它们的主要区别: <b>IList 接口</b> IList 接口是C#中定义的一个泛型接口,位于 System.Collections 命名空间。它派生自 ICollection 接口,定义了一个可以通过索引访问的有序集合。 ```c# IList 接口包含一系列索引化的属性和方法,允许按索引访问、插入、移除元素等。 由于是接口,它只定义了成员的契约,而不提供具体的实现。类似于 IEnumera
158 2
|
1月前
|
开发框架 安全 .NET
C# .NET面试系列一:基础语法
<h2>基础语法 #### 1. 字符串中 string str = null 和 string str = "" 和 string str = string.Empty 的区别? string str=null: ```c# 这表示字符串变量str被初始化为null,即它不引用任何对象。这与空字符串是不同的,因为空字符串是一个具有零长度的字符串对象,不会分配内存空间 ``` string.Empty: ```c# 这表示字符串变量str被初始化为空字符串,即一个具有零长度的字符串对象。这与null是不同的,因为str引用了一个空字符串对象 ``` string str="" :
64 1