C# 基础知识系列-7 Linq详解
前言
在上一篇中简单介绍了Linq的入门级用法,这一篇尝试讲解一些更加深入的使用方法,与前一篇的结构不一样的地方是,这一篇我会先介绍Linq里的支持方法,然后以实际需求为引导,分别以方法链的形式和类SQL的形式写出来。
前置概念介绍
Predicate<T>
谓词、断言,等价于Func<T,bool>
即返回bool的表达式Expression<TDelegate>
表达式树,这个类很关键,但是在这里会细说,我们会讲它的一个特殊的泛型类型:Expression<Func<T,bool>>
这个在某些数据源的查询中十分重要,它代表lambda表达式中一种特殊的表达式,即没有大括号和return
关键字的那种。
我们先准备两个类:
- Student/学生类:
/// <summary>
/// 学生
/// </summary>
public class Student
{
/// <summary>
/// 学号
/// </summary>
public int StudentId { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 班级
/// </summary>
public string Class { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
}
Subject/科目类:
/// <summary>
/// 科目
/// </summary>
public class Subject
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 年级
/// </summary>
public string Grade { get; set; }
/// <summary>
/// 学号
/// </summary>
public int StudentId { get; set; }
/// <summary>
/// 成绩
/// </summary>
public int Score { get; set; }
}
Subject 和Student通过学号字段一一关联,实际工作中数据表有可能会设计成这。
那么先虚拟两个数据源:IEnumerable<Student> students
和 IEnumerable<Subject> subjects
。先忽略这两个数据源的实际来源,因为在开发过程中数据来源有很多种情况,有数据库查询出来的结果、远程接口返回的结果、文件读取的结果等等。不过最后都会整理成IEnumerable<T>
的子接口或实现类的对象。
常见方法介绍
Where 过滤数据,查询出符合条件的结果
where的方法声明:
public IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate)
可以看出不会转换数据类型,通过给定的lambda表达式或者一个方法进行过滤,获取返回true的元素。
示例:
// 获取年纪大于10但不大于12的同学们
List<Student> results = students.Where(t=>t.Age >10 && t.Age<= 12).ToList();
注意在调用ToList之后数据才会实质上查询出来。
Group 分组,依照指定内容进行分组
Group的方法声明有很多种:
最常用的一种是:
public static IEnumerable<System.Linq.IGrouping<TKey,TSource>> GroupBy<TSource,TKey> (this IEnumerable<TSource> source, Func<TSource,TKey> keySelector);
示例:
//将学生按照班级进行分组
List<IGrouping<string,Student>> list = students.GroupBy(p => p.Class).ToList();
OrderBy/OrderByDescending 进行排序,按条件升序/降序
它们是一对方法,一个是升序一个降序,其声明是一样的:
常用的是:
public static System.Linq.IOrderedEnumerable<TSource> OrderBy<TSource,TKey> (this IEnumerable<TSource> source, Func<TSource,TKey> keySelector);
示例:
//按年龄的升序排列:
List<Student> results = students.OrderBy(p => p.Age).ToList();
//按年龄的降序排列:
List<Student> results = students.OrderByDescending(p => p.Age).ToList();
First/Last 获取数据源的第一个/最后一个
这组方法有两个常用的重载声明:
First:
// 直接获取第一个
public static TSource First<TSource> (this IEnumerable<TSource> source);
// 获取满足条件的第一个
public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
Last:
// 直接获取最后一个
public static TSource Last<TSource> (this IEnumerable<TSource> source);
// 获取最后一个满足条件的元素
public static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
示例:
Student student = students.First();// 等价于 students[0];
Student student = students.First(p=>p.Class == "一班");//获取数据源中第一个一班的同学
Student student = students.Last();//最后一个学生
Student student = students.Last(p=>p.Class == "三班");//获取数据源中最后一个三班的同学
注意:
- 在某些数据源中使用Last会报错,因为对于一些管道类型的数据源或者说异步数据源,程序无法确认最后一个元素的位置,所以会报错。解决方案:先使用OrderBy对数据源进行一次排序,使结果与原有顺序相反,然后使用First获取
- 当数据源为空,或者不存在满足条件的元素时,调用这组方法会报错。解决方案:调用FirstOrDefault/LastOrDefault,这两组方法在无法查询到结果时会返回一个默认值。
Any/All 是否存在/是否都满足
Any:是否存在元素满足条件
有两个版本,不过意思可能不太一样:
public static bool Any<TSource> (this IEnumerable<TSource> source);//数据源中是否有数据
//================
//是否存在满足条件的数据
public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
All :是否都满足条件:
public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
示例:
// 是否有学生
bool isAny = students.Any();
// 是否有五班的同学
bool isFive = students.Any(p=>p.Class == "五班");
// 是否所有学生的年纪都不小于9岁
bool isAll = students.All(p=>p.Age >= 9);
Skip 略过几个元素
Skip一共有三个衍生方法:
第一个:Skip 自己: 略过几个元素,返回剩下的元素内容
public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count);
第二个:SkipLast,从尾巴开始略过几个元素,返回剩下的元素内容
public static IEnumerable<TSource> SkipLast<TSource> (this IEnumerable<TSource> source, int count);
第三个:SkipWhile,跳过满足条件的元素,返回剩下的元素
public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
示例:
// 不保留前10个学生
List<Student> results = students.Skip(10).ToList();
// 不保留后10个学生
List<Student> results = students.SkipLast(10).ToList();
// 只要非一班的学生
List<Student> results = students.SkipWhere(p=>p.Class=="一班").ToList();
//上一行代码 等价于 = students.Where(p=>p.Class != "一班").ToList();
Take 选取几个元素
Take与Skip一样也有三个衍生方法,声明的参数类型也一样,这里就不对声明做介绍了,直接上示例。
//选取前10名同学
List<Student> results = students.Take(10).ToList();
// 选取最后10名同学
List<Student> results = students.TakeLast(10).ToList();
//选取 一班的学生
List<Student> results = students.TakeWhile(p=>p.Class=="一班").ToList();
// 上一行 等价于 = students.Where(p=>p.Class=="一班").ToList();
在使用Linq写分页的时候,就是联合使用Take和Skip这两个方法:
int pageSize = 10;//每页10条数据
int pageIndex = 1;//当前第一页
List<Student> results = students.Skip((pageIndex-1)*pageSize).Take(pageSize).ToList();
其中 pageIndex可以是任意大于0 的数字。Take和Skip比较有意思的地方就是,如果传入的数字比数据源的数据量大,根本不会爆粗,只会返回一个空数据源列表。
Select 选取
官方对于Select的解释是,将序列中的每个元素投影到新的表单里。我的理解就是,自己 定义一个数据源单个对象的转换器,然后按照自己的方式对数据进行处理,选择出一部分字段,转换一部分字段。
所以按我的理解,我没找到java8的同效果方法。(实际上java用的是map,所以没找到,
C# 基础知识系列-7 Linq详解的更多相关文章
- vue.js基础知识篇(6):组件详解
第11章:组件详解 组件是Vue.js最推崇也最强大的功能之一,核心目标是可重用性. 我们把组件代码按照template.style.script的拆分方式,放置到对应的.vue文件中. 1.注册 V ...
- 《Java基础知识》Java注解"@"详解
Java注解含义: Java注解,顾名思义,注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的.Java注解又叫java标注,java提供了一套机制,使得 ...
- 《Java基础知识》Java锁详解(volatile,synchronized等)
volatile: 让变量每次在使用的时候,都从主存中取. volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执 ...
- linux基础知识3_根文件系统详解
文件系统: rootfs:根文件系统 /boot:系统启动相关的文件,如内核.initrd以及grub /dev:设备文件 块设备:随机访问 字符设备:线性访问,按字符为单位 设备号:主设备号(maj ...
- JavaScript基础知识之——Location 对象详解
属性 描述 location.hash 设置或取得 URL 中的锚 location.host 设置或取得 URL 中主机(包括端口号) location.hostname 设置或取得 URL 中的主 ...
- vue.js基础知识篇(2):指令详解
第三章:指令 1.语法 指令以v-打头,它的值限定为绑定表达式,它负责的是按照表达式的值应用某些行为到DOM上. 内部指令有v-show,v-else,v-model,v-repeat,v-for,v ...
- 《Java基础知识》Java字符串详解
本文内容: String类的概述 String类的使用步骤 String类的常用方法 本文目的: 能够使用String类的构造方法创建字符串对象 能够明确String类的构造方法创建对象,和直接赋值创 ...
- 《Java基础知识》Java异常处理详解
1. Java 中的异常 前言:Java 中的异常处理是处理程序运行错误时的强大机制之一,它可以保证应用程序的正常流程. 首先我们将了解java异常.异常的类型以及受查和非受查异常之间的区别. 1.1 ...
- 《Java基础知识》Java 泛型详解
JDK 1.5 之后,Java 通过泛型解决了容器类型安全这一问题,而几乎所有人接触泛型也是通过Java的容器.那么泛型究竟是什么? 泛型的本质是参数化类型:也就是说,泛型就是将所操作的数据类型作为参 ...
随机推荐
- Filter过滤器Listener:监听器
Filter过滤器 1. 概念 web中的过滤器:当访问服务器资源是,过滤器可以将请求拦截下来,完成一些特殊功能: 过滤器的作用 完成通用的操作:例如登录验证.统一编码处理.敏感字符过滤... 快速入 ...
- SpringBoot&Shiro实现用户认证
SpringBoot&Shiro实现用户认证 实现思路 思路:实现认证功能主要可以归纳为3点 1.定义一个ShiroConfig配置类,配置 SecurityManager Bean , Se ...
- Ansible-基本概述
为什么要自动化运维 纯手动软件安装部署方式 我们以 10 台机器部署 Nginx 为例.部署步骤如下: 1.通过 ssh 登录一台机器: 2.yum install -y nginx 或者 获取安装包 ...
- 解决WebMvcConfigurer下的addViewControllers无法找到制定页面
解决WebMvcConfigurer下的addViewControllers无法找到制定页面 这种都已经配置了拦截跳转,但无效的原因是,没有加载thymeleaf依赖 <dependency&g ...
- [Cts-Verifier]waiver-Camera-ITS-Test
[问题描述] 工具:Cts-Verifier-9.0-R11.apk 测试Camera ITS Test时,点击该测试项后verifier apk闪退.重新打开后该项未pass变绿. [问题结论] A ...
- 前端每日实战:55# 视频演示如何用纯 CSS 创作一个太阳、地球、月亮的运转模型
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/RJjQYY 可交互视频 此视频是可 ...
- python读入写入中文名图片
import os import cv2 import numpy as np # 读入中文命名图片 def cv_imread(in_path): cv_img = cv2.imdecode(np. ...
- ZipArchive(解压文件)
一.首先介绍minizip 的使用方法 ziparchive是基于开源代码”MiniZip”的zip压缩与解压的Objective-C 的Class,使用起来非常的简单方法:从http://code. ...
- java面试汇总一
第一部分 Java SE基础(1) 1.1 java的8种基本数据类型 装箱 拆箱 1.1.1 8种基本的数据类型 1.1.2装箱 拆箱 自动装箱是 Java 编译器在基本数据类型和对应的对象包 ...
- mybatis进阶案例之多表查询
mybatis进阶案例之多表查询 一.mybatis中表之间的关系 在数据库中,实体型之间的关系主要有如下几种: 1.一对一 如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之 ...