[C#] 进阶 - LINQ 标准查询操作概述
LINQ 标准查询操作概述

序
一、按标准执行方式分类
二、排列数据

| 方法名 | 说明 | C# 查询表达式语法 |
| OrderBy | 按升序对值进行排序。 | orderby |
| OrderByDescending | 按降序对值进行排序。 | orderby … descending |
| ThenBy | 按升序执行次要排序。 | orderby …, … |
| ThenByDescending | 按降序执行次要排序。 | orderby …, … descending |
| Reverse | 颠倒集合中的元素的顺序。 | X |
示例:
var words = new[] { "the", "quick", "brown", "fox", "jumps" };
var query = from word in words
orderby word.Length
select word;
foreach (var word in query)
{
Console.WriteLine(word);
}
下面通过演示使用 orderby 进行升序排序:按字符串长度

var words = new[] { "the", "quick", "brown", "fox", "jumps" };
var query = from word in words
orderby word.Substring(,) descending
select word;
foreach (var word in query)
{
Console.WriteLine(word);
}
下面通过演示使用 orderby descending 进行降序排序:按字符串的第一个字母

var words = new[] { "the", "quick", "brown", "fox", "jumps" };
var query = from word in words
orderby word.Length, word.Substring(, )
select word;
foreach (var word in query)
{
Console.WriteLine(word);
}
下面通过演示使用 orderby 进行主要和次要排序:先升序按字符串长度(主)、再升序按字符串的第一个字母(次)

var words = new[] { "the", "quick", "brown", "fox", "jumps" };
var query = from word in words
orderby word.Length, word.Substring(, ) descending
select word;
foreach (var word in query)
{
Console.WriteLine(word);
}
下面通过演示使用 orderby descending 进行主要和次要排序:先升序按字符串长度(主)、再降序按字符串的第一个字母(次)

三、Set 操作
LINQ 中的 Set 操作是指根据相同或不同集合中是否存在等效元素来生成结果集的查询操作。
| 方法名 | 说明 |
C# 查询表达式语法 |
|
Distinct |
从集合移除重复值。 |
X |
|
Except |
返回差集,差集是指位于一个集合但不位于另一个集合的元素。 |
X |
|
Intersect |
返回交集,交集是指同时出现在两个集合中的元素。 |
X |
|
Union |
返回并集,并集是指位于两个集合中任一集合的唯一的元素。 |
X |
图解 Set 操作
(1)Distinct: 返回的序列包含输入序列的唯一元素。

(2)Except: 返回的序列只包含位于第一个输入序列但不位于第二个输入序列的元素。

(3)Intersect: 返回的序列包含两个输入序列共有的元素。



四、过滤数据
| 方法名 | 说明 | C# 查询表达式语法 |
| OfType | 根据值强制转换为指定类型的能力选择值。 | X |
| Where | 选择基于谓词函数的值。 | where |
string[] words = { "the", "quick", "brown", "fox", "jumps" };
var query = from word in words
where word.Length ==
select word;
foreach (var word in query)
{
Console.WriteLine(word);
}
使用 where 子句来从数组中筛选那些具有特定长度的字符串

五、量词操作
限定符运算返回一个 Boolean 值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件。

|
方法名 |
说明 |
C# 查询表达式语法 |
| All |
确定是否序列中的所有元素都满足条件。 |
X |
| Any |
确定序列中是否有元素满足条件。 |
X |
|
Contains |
确定序列是否包含指定的元素。 |
X |
六、投影操作
| 方法名 | 说明 | C# 查询表达式语法 |
| Select | 映射基于转换函数的值。 | select |
| SelectMany | 映射基于转换函数的值序列,然后将它们展平为一个序列。 | 使用多个 from 子句 |
var words = new[] { "the", "quick", "brown", "fox", "jumps" };
var query = from word in words
select word.Substring(,);
foreach (var word in query)
{
Console.WriteLine(word);
}
Select:下面的示例使用 select 子句来映射字符串列表中每个字符串的第一个字母

var phrases = new List<string>() { "an apple a day", "the quick brown fox" };
var query = from phrase in phrases
from word in phrase.Split(' ')
select word;
foreach (var word in query)
{
Console.WriteLine(word);
}
SelectMany:下面的示例使用多个 from 子句来映射字符串列表中每个字符串中的每个单词

Select() 和 SelectMany() 的工作都是依据源值生成一个或多个结果值。Select() 为每个源值生成一个结果值。因此,总体结果是一个与源集合具有相同元素数目的集合。与之相反,SelectMany() 将生成单一总体结果,其中包含来自每个源值的串联子集合。作为参数传递到 SelectMany() 的转换函数必须为每个源值返回一个可枚举值序列。然后,SelectMany() 将串联这些可枚举序列以创建一个大的序列。
下面两个插图演示了这两个方法的操作之间的概念性区别。在每种情况下,假定选择器(转换)函数从每个源值中选择一个由花卉数据组成的数组。
下图描述 Select() 如何返回一个与源集合具有相同元素数目的集合。

下图描述 SelectMany() 如何将中间数组序列串联为一个最终结果值,其中包含每个中间数组中的每个值。

示例
下面的示例比较 Select() 和 SelectMany() 的行为。代码将通过从源集合的每个花卉名称列表中提取前两项来创建一个“花束”。在此示例中,转换函数 Select 使用的“单一值”本身就是一个值集合。这需要额外的 foreach 循环,以便枚举每个子序列中的每个字符串。
static void Main(string[] args)
{
var bouquets = new List<Bouquet>()
{
new Bouquet {Flowers = new List<string> {"sunflower", "daisy", "daffodil", "larkspur"}},
new Bouquet {Flowers = new List<string> {"tulip", "rose", "orchid"}},
new Bouquet {Flowers = new List<string> {"gladiolis", "lily", "snapdragon", "aster", "protea"}},
new Bouquet {Flowers = new List<string> {"larkspur", "lilac", "iris", "dahlia"}}
}; IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);
IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers); Console.WriteLine("query1 - Select():");
foreach (IEnumerable<string> collection in query1)
{
foreach (var item in collection)
{
Console.WriteLine(item);
}
} Console.WriteLine("\nquery2 - SelectMany():");
foreach (var item in query2)
{
Console.WriteLine(item);
} Console.Read();
} class Bouquet
{
public List<string> Flowers { get; set; }
}

七、划分数据
LINQ 中的分区指的是在不重新排列元素的情况下,将输入序列划分为两部分,然后返回其中一个部分的操作。
|
运算符名称 |
说明 |
C# 查询表达式语法 |
|
Skip |
跳过序列中的指定位置之前的元素。 |
X |
|
SkipWhile |
基于谓词函数跳过元素,直到某元素不再满足条件。 |
X |
|
Take |
提取序列中的指定位置之前的元素。 |
X |
|
TakeWhile |
基于谓词函数提取元素,直到某元素不再满足条件。 | X |
八、联接操作
将两个数据源“联接”就是将一个数据源中的对象与另一个数据源中共享某个通用特性的对象关联起来。
当查询所面向的数据源相互之间具有无法直接领会的关系时,联接就成为一项重要的运算。在面向对象的编程中,这可能意味着在未建模对象之间进行关联,例如对单向关系进行反向推理。下面是单向关系的一个示例:Customer 类有一个类型为 City 的属性,但 City 类没有作为 Customer 对象集合的属性。如果你具有一个 City 对象列表,并且要查找每个城市中的所有客户,则可以使用联接运算完成此项查找。
LINQ 框架中提供的联接方法包括 Join 和 GroupJoin。这些方法执行同等联接,即根据两个数据源的键是否相等来匹配这两个数据源的联接。(与此相较,Transact-SQL 支持除“等于”之外的联接运算符,例如“小于”运算符。)用关系数据库术语表达,就是说 Join 实现了内部联接,这种联接只返回那些在另一个数据集中具有匹配项的对象。GroupJoin 方法在关系数据库术语中没有直接的等效项,但它实现了内部联接和左外部联接的超集。左外部联接是这样一种联接:它返回第一个(左)数据源的每个元素,即使该元素在另一个数据源中没有关联元素。

|
方法名 |
描述 |
C# 查询表达式语法 |
| Join |
根据键选择器函数联接两个序列并提取值对。 |
join … in … on … equals … |
|
GroupJoin |
根据键选择器函数联接两个序列,并对每个元素的结果匹配项进行分组。 |
join … in … on … equals … into … |
九、分组数据

|
方法名 |
说明 |
C# 查询表达式语法 |
|
GroupBy |
对共享公共特性的元素进行分组。 每个组都由一个 IGrouping<TKey, TElement> 对象表示。 |
group … by - 或 - group … by … into … |
|
ToLookup |
根据键选择器函数将元素插入到 Lookup<TKey, TElement>(一个一对多字典)中。 |
X |
var numbers = new List<int>() { , , , , , , , , , };
IEnumerable<IGrouping<bool, int>> query = from number in numbers
group number by number % == ;
foreach (var group in query)
{
Console.WriteLine($"{(group.Key ? "偶数" : "基数")}:");
foreach (var i in group)
{
Console.WriteLine(i);
}
}
使用 group by 子句根据列表中的整数是奇数还是偶数进行分组

十、生成操作
|
方法名 |
说明 |
C# 查询表达式语法 |
|
DefaultIfEmpty |
将空集合替换为具有默认值的单一实例集合。 |
X |
| Empty |
返回空集合。 |
X |
| Range |
生成包含数字序列的集合。 |
X |
|
Repeat |
生成包含一个重复值的集合。 |
X |
十一、等值操作
| 方法名 | 说明 | C# 查询表达式语法 |
| SequenceEqual | 通过成对地比较元素确定两个序列是否相等。 | X |
十二、元素操作
元素操作从一个序列返回单个特定元素。
|
方法名 |
说明 |
C# 查询表达式语法 |
|
ElementAt |
返回集合中指定索引处的元素。 |
X |
|
ElementAtOrDefault |
返回集合中指定索引处的元素;如果索引超出范围,则返回默认值。 |
X |
|
First |
返回集合中的第一个元素或满足条件的第一个元素。 |
X |
|
FirstOrDefault |
返回集合中的第一个元素或满足条件的第一个元素。 如果没有这样的元素,则返回默认值。 |
X |
| Last |
返回集合中的最后一个元素或满足条件的最后一个元素。 |
X |
|
LastOrDefault |
返回集合中的最后一个元素或满足条件的最后一个元素。 如果没有这样的元素,则返回默认值。 |
X |
|
Single |
返回集合中的唯一元素或满足条件的唯一元素。 |
X |
|
SingleOrDefault |
返回集合中的唯一元素或满足条件的唯一元素。 如果没有这样的元素或集合不是正好包含一个元素,则返回默认值。 |
X |
十三、转换数据类型
转换方法更改输入对象的类型。
LINQ 查询中的转换运算可用于各种应用程序。下面是一些示例:
(1)Enumerable.AsEnumerable<TSource> 方法可用于隐藏类型的标准查询运算符的自定义实现。
(2)Enumerable.OfType<TResult> 方法可用于启用非参数化集合以进行 LINQ 查询。
(3)Enumerable.ToArray<TSource>、Enumerable.ToDictionary<TSource, TKey>、Enumerable.ToList<TSource> 和 Enumerable.ToLookup<TSource, TKey> 方法可用于强制立即执行查询,而非推迟到枚举查询时。
| 方法名 | 说明 | C# 查询表达式语法 |
| AsEnumerable | 返回类型为 IEnumerable<T> 的输入。 | X |
| AsQueryable | 将(泛型)IEnumerable 转换为(泛型)IQueryable。 | X |
| Cast | 将集合的元素强制转换为指定类型。 |
使用显式类型化的范围变量。 例如: from string str in words |
| OfType | 根据值强制转换为指定类型的能力筛选值。 | X |
| ToArray | 将集合转换为数组。 此方法强制执行查询。 | X |
| ToDictionary | 根据键选择器函数将元素放入 Dictionary<TKey, TValue> 中。 此方法强制执行查询。 | X |
| ToList | 将集合转换为 List<T>。 此方法强制执行查询。 | X |
| ToLookup | 根据键选择器函数将元素放入 Lookup<TKey, TElement>(一对多字典)中。 此方法强制执行查询。 | X |
示例:
static void Main(string[] args)
{
var plants = new Plant[]
{
new CarnivorousPlant {Name = "Venus Fly Trap", TrapType = "Snap Trap"},
new CarnivorousPlant {Name = "Pitcher Plant", TrapType = "Pitfall Trap"},
new CarnivorousPlant {Name = "Sundew", TrapType = "Flypaper Trap"},
new CarnivorousPlant {Name = "Waterwheel Plant", TrapType = "Snap Trap"}
}; var query = from CarnivorousPlant plant in plants
where plant.TrapType == "Snap Trap"
select plant; foreach (var carnivorousPlant in query)
{
Console.WriteLine(carnivorousPlant.Name);
} Console.Read();
} class Plant
{
public string Name { get; set; }
} class CarnivorousPlant : Plant
{
public string TrapType { get; set; }
}
使用显式类型化的范围变量将类型强制转换为子类型,然后才访问仅在此子类型中提供的成员。

十四、串联操作
串联是指将一个序列追加到另一个序列的运算。
下图演示对两个字符序列执行的串联运算。

|
方法名 |
说明 |
C# 查询表达式语法 |
|
Concat |
串联两个序列以组成一个序列。 |
X |
十五、聚合操作
聚合运算从值集合计算单个值。从一个月的日温度值计算日平均温度就是聚合运算的一个示例。

|
方法名 |
说明 |
C# 查询表达式语法 |
|
Aggregate |
对集合值执行自定义聚合运算。 |
X |
|
Average |
计算值集合的平均值。 |
X |
| Count |
对集合中的元素进行计数,还可以仅对满足某一谓词函数的元素进行计数。 |
X |
|
LongCount |
对大型集合中的元素进行计数,还可以仅对满足某一谓词函数的元素进行计数。 |
X |
| Max |
确定集合中的最大值。 |
X |
| Min |
确定集合中的最小值。 |
X |
|
Sum |
计算集合中值的总和。 |
X |
传送门
入门:《走进 LINQ 的世界》
进阶:《LINQ 标准查询操作概述》(强烈推荐)
技巧:《Linq To Objects - 如何操作字符串》 和 《Linq To Objects - 如何操作文件目录》
【参考】https://msdn.microsoft.com/zh-cn/library/bb397896(v=vs.100).aspx
【来源】部分图片摘自微软官方文档
[C#] 进阶 - LINQ 标准查询操作概述的更多相关文章
- C# LINQ学习笔记二:LINQ标准查询操作概述
本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5801249.html,记录一下学习过程以备后续查用. “标准查询运算符”是组成语言集成查询 (LINQ) 模式 ...
- C#3.0新增功能09 LINQ 标准查询运算符 04 运算
连载目录 [已更新最新开发文章,点击查看详细] 本篇主要介绍标准查询运算符的常用运算功能. 01 对数据排序 排序操作基于一个或多个属性对序列的元素进行排序. 第一个排序条件对元素执行主要排序. ...
- C#3.0新增功能09 LINQ 标准查询运算符 01 概述
连载目录 [已更新最新开发文章,点击查看详细] 标准查询运算符 是组成 LINQ 模式的方法. 这些方法中的大多数都作用于序列:其中序列指其类型实现 IEnumerable<T> 接 ...
- .NET LINQ标准查询运算符
标准查询运算符概述 “标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法. 大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了 IEnumerable<T> ...
- Linq 标准查询操作符三
本文介绍了LINQ标准查询操作符.没有这些操作符,LINQ就不会存在.本文为理解这些操作符的功能提供了很好的基础.了解它们将会很有帮助,因为LINQ的各种Provider都是基于这些操作符来完成各自丰 ...
- LINQ 标准查询操作符
本文介绍了LINQ标准查询操作符.没有这些操作符,LINQ就不会存在.本文为理解这些操作符的功能提供了很好的基础.了解它们将会很有帮助,因为LINQ的各种Provider都是基于这些操作符来完成各自丰 ...
- LINQ标准查询运算符的执行方式-延时之流式处理
linq的延时执行是指枚举时才去一个个生成结果元素. 流式处理是linq延时执行的一种,在生成元素前不需要获取所有源元素,只要获取到的源元素足够计算时,便生成结果元素. 流式处理的标准查询运算符返回值 ...
- LINQ标准查询操作符详解(转)
一. 关于LINQ LINQ 英文全称是“Language-Integrated Query”,中文为“语言集成查询”,它是微软首席架构师.Delphi 之父和C# 之父——Anders ...
- 【LINQ标准查询操作符总结】之聚合操符
C# 中的LINQ 提供了两种操作方式,查询表达式和查询操作符,所有的查询表达式都有对应的查操作符类替代,查询表达式有点“类” SQL,在代码中写SQL,总觉得不够“优雅”,使用查询操作符就显得“优 ...
随机推荐
- .NET Core全新路线图
.NET Core / ASP.NET Core 1 RTM发布两周后,社区也很积极,收到了非常多的反馈,上周五微软的scott Hunter 在dotnet团队官方博客上发布了.NET Core全新 ...
- System.FormatException: GUID 应包含带 4 个短划线的 32 位数(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。
在NHibernate数据库查询中出现了这个错误,由于是数据库是mysql的,当定义的字段为char(36)的时候就会出现这个错误. [解决方法] 将char(36) 改成varchar(40)就行了 ...
- Mediaplayer error (-19,0)
Android MediaPlayer 发生 error (-19,0) 错误解决方法. 引起原因:由于多次实例化MediaPlayer.start() 进行播放操作引起的.由于没有及时释放内存资源导 ...
- 从零开始编写自己的C#框架(27)——什么是开发框架
前言 做为一个程序员,在开发的过程中会发现,有框架同无框架,做起事来是完全不同的概念,关系到开发的效率.程序的健壮.性能.团队协作.后续功能维护.扩展......等方方面面的事情.很多朋友在学习搭建自 ...
- Unity3D框架插件uFrame实践记录(一)
1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...
- (转)从0开始搭建SQL Server AlwaysOn 第一篇(配置域控+域用户DCADMIN)
原文地址: http://www.cnblogs.com/lyhabc/p/4678330.html 实验环境: 准备工作 软件准备 (1) SQL Server 2012 (2) Windows S ...
- 换个角度看微信小程序[推荐]
去年参加几次技术沙龙时,我注意到一个有意思的现象:与之前大家统一接受的换名片不同,有些人并不愿意被添加微信好友--"不好意思,不熟的人不加微信". 这个现象之所以有意思,是因为名片 ...
- could not initialize proxy - no Session
这是一个精典的问题:因为我们在hibernate里面load一个对象出来时,用到的是代理对象,也就是说当我们在执行load方法时并没有发sql语句,而是返回一个proxy对象.只有当们具体用到哪个ge ...
- ASP.NET Aries JSAPI 文档说明:AR.Form、AR.Combobox
AR.Form 文档 1:对象或属性: 名称 类型 说明 data 属性 编辑页根据主键请求回来的数据 method 属性 用于获取数据的函数指向,默认值Get objName 属性 用于拦截form ...
- Mac OS X上编写 ASP.NET vNext(一)KRE环境搭建
最新的asp.net vnext已经可以支持在mac上运行了,当然用的是mono.相比linux来说,mac的安装略显繁琐.对于大部分用Windows开发asp.net的程序员来说,初次配置还是很费时 ...