LINQ进阶(深入理解C#)11 查询表达式和LINQ to Objects
11.4 let 子句与透明标识符#
11.4.1 用let来进行中间计算#
这段代码运行正常,不过它调用了“可怕的” Length属性两次——一次是对用户进行排序,一次用于显示。
var query = from user in SampleData.AllUsers
orderby user.Name.Length //first
select user.Name;
foreach (var name in query)
{
Console.WriteLine("{0}: {1}", name.Length, name); //seconed
}
这正是let子句的用武之地,它对一个表达式进行求值,并引入一个新的范围变量。不过对于每个用户只使用了一次Length属性。
var query = from user in SampleData.AllUsers
let length = user.Name.Length //only one
orderby length
select new { Name = user.Name, Length = length };
foreach (var entry in query)
{
Console.WriteLine("{0}: {1}", entry.Length, entry.Name);
}
11.4.2 透明标识符#
我们在最后的投影中使用了两个范围变量,不过Select方法只对单个序列起作用。如何把范围变量合并在一起呢?
答案是,创建一个匿名类型来包含两个变量,不过需要进行一个巧妙的转换,以便看起来就像在select和orderby子句中实际应用了两个参数。
let子句为了实现目标,再一次调用了Select,并为结果序列创建匿名类型,最终创建了一个新的范围变量。
查询表达式被转换为如下内容:
11.5 连接#
11.5.2 使用join...into子句进行分组连接#
分组连接(group join)结果中的每个元素由
左边序列(使用它的原始范围变量)的某个元素和右边序列的所有匹配元素的序列组成。
后者用一个新的范围变量表示,该变量由join子句中into后面的标识符指定。
var query = from defect in SampleData.AllDefects
join subscription in SampleData.AllSubscriptions
on defect.Project equals subscription.Project
into groupedSubscriptions
select new { Defect = defect, Subscriptions = groupedSubscriptions };
foreach (var entry in query)
{
Console.WriteLine(entry.Defect.Summary);
foreach (var subscription in entry.Subscriptions)
{
Console.WriteLine(" {0}", subscription.EmailAddress);
}
}
对于分组连接来说,在左边序列和结果序列之间是一对一的对应关系,即使左边序列中的某些元素在右边序列中没有任何匹配的元素,也无所谓。
这是非常重要的,有时会用于模拟SQL的左外连接。在左边元素不匹配任何右边元素的时候,嵌入序列就是空的。与内连接一样,分组连接要对右边序列进行缓冲,而对左边序列进行流处理
select...join into 相当于 GroupJoin.#
11.5.3 使用多个from子句进行交叉连接和合并序列#
它就像指定了多表查询的笛卡儿积。实际上,大多数时候,它正是交叉连接的用法。
var query = from user in SampleData.AllUsers
from project in SampleData.AllProjects
select new { User = user, Project = project };
foreach (var pair in query)
{
Console.WriteLine("{0}/{1}",
pair.User.Name,
pair.Project.Name);
}
右边序列依赖于左边元素的交叉连接
多个from 相当于 selectMany#
//11.6 两个from
var query = from left in Enumerable.Range(1, 4)
from right in Enumerable.Range(11, left)
select new { Left = left, Right = right };
foreach (var pair in query)
{
Console.WriteLine("Left={0}; Right={1}", pair.Left, pair.Right);
}
//转化为标准查询操作符:selectMany
var lambda = Enumerable.Range(1, 4).SelectMany(
left => Enumerable.Range(11, left),
(left, right) =>
new { Left = left, Right = right });
foreach (var pair in lambda)
{
Console.WriteLine("Left={0}; Right={1}", pair.Left, pair.Right);
}
作者:【唐】三三
出处:https://www.cnblogs.com/tangge/p/14642197.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-04-10 创建索引,SQL优化