前言

继续介绍一些复杂的linq。

正文

groupjoin 这个函数:

有department

public class Deployment
{
public string Id { get; set; } public Deployment(string id)
{
Id = id;
}
}

有Employee:

public class Employee
{
public string DepartmentId { get; set; } public string Name { get; set; } public Employee(string name, string deploymentId)
{
Name = name;
DepartmentId = deploymentId;
}
}

现在要实现Deployment和Employee,一对多的关系:

List<Deployment> a = new List<Deployment>()
{
new Deployment("1"),
new Deployment("2"),
}; List<Employee> e = new List<Employee>()
{
new Employee("张三","1"),
new Employee("李四","1"),
new Employee("王五","2"),
};

如果我们使用join的话,那么就是:

Deployment("1") Employee("张三","1")
Deployment("1") Employee("李四","1")
Deployment("2") Employee("王五","2")

就是这种平铺的关系。然后再使用group by。

Deployment("1")
Employee("张三","1")
Employee("李四","1")
Deployment("2")
Employee("王五","2")

现在有一个函数可以直接到达这种效果,那么就是groupjoin:

static void Main(string[] args)
{
List<Deployment> a = new List<Deployment>()
{
new Deployment("1"),
new Deployment("2"),
}; List<Employee> e = new List<Employee>()
{
new Employee("张三","1"),
new Employee("李四","1"),
new Employee("王五","2"),
}; var c = a.GroupJoin(e, deployment => deployment.Id,
employee => employee.DepartmentId,
(department, exployees) =>(department.Id, exployees)
); Console.ReadKey();
}

其实可以看到这个exployees,最终运行时是一个Igroup类型,这和join还有group by不同之处。

然后这里写一下join和group by的。

static void Main(string[] args)
{
List<Deployment> a = new List<Deployment>()
{
new Deployment("1"),
new Deployment("2"),
new Deployment("3")
}; List<Employee> e = new List<Employee>()
{
new Employee("张三","1"),
new Employee("李四","1"),
new Employee("王五","2"),
}; var f = from a1 in a
join e1 in e on a1.Id equals e1.DepartmentId into temps
from tt in temps.DefaultIfEmpty()
select (a1.Id, (a1.Id, tt));
var d = from f1 in f
group f1 by f1.Id; Console.ReadKey();
}

这里要说明的就是groupjoin 是一个左连接。

上面用的是linq的查询表达式,因为join 方法其实是inner join。

对于表达式来说其实最终还是生成方法而已,IL 来说没有表达式这回事,可以理解为c#的语法糖。

看下如果上述的linq用方法来怎么写吧。

其实还是用的是groupjoin:

这里可以看出,其实上述这个linq表达式就是groupjoin 然后用selectmany拆开,然后在用group再聚合。。

如果你只需要获取每个部门下的员工,用groupjoin 效率是更高的。

当然这里主要是说明linq 的表达式最终都是方法,语法糖而已。表达式是为了让我们更加清晰的去描述。

如果写一些复杂的linq,那么最好去用linq表达式。通过如果是groupjoin 就能实现的,就没必要去使用,这可能效率更低。

这里提到了selectmany,那么就讲述一下selectmany。 group by 是聚合,那么selectmany就是拆分。

public class BasketballTeam
{
public string Name { get; set; } public string[] TeamMember;
} static void Main(string[] args)
{
List<BasketballTeam> list = new List<BasketballTeam>();
BasketballTeam basketballTeam = new BasketballTeam();
basketballTeam.Name = "无敌球队";
basketballTeam.TeamMember = new string[] { "张三", "李四", "王五" };
BasketballTeam basketballTeam1 = new BasketballTeam();
basketballTeam1.Name = "小新球团";
basketballTeam1.TeamMember = new string[] { "张嘛子", "李老帽", "王七三" };
list.Add(basketballTeam);
list.Add(basketballTeam1);
var a = list.SelectMany(u=> u.TeamMember, (u,s)=> u.Name + " " + s); foreach (var item in a)
{
Console.WriteLine(item);
}
Console.ReadKey();
}

selectMany 就是用来处理集合的集合的,是一个展开过程。

上面代码是遍历一组球队的全部成员。

有兴趣可以去看下代码,其实都能猜到,就是两个foreach 循环的封装。

下面介绍一下c# 匿名类型对linq使用:

如果临时使用,那么可以使用匿名类型。

匿名类型其实不是说真的匿名,其实是编译的时候会生成一个类。

如果两者完全一样,那么将会生成一个类,如果只要有一点结构不同,那么会生成两个类。

因为上面一致,所以赋值。

顺序不一致,依然生成不同的类。

不过现在元组替代了匿名类型,因为元组在方法外部也可以使用。

然后值得注意的是匿名类型是引用类型,而元组是值类型,如果经常拷贝且内存超过128位就用匿名,否则就是元组。

其实不用纠结元组和匿名,就是元组的功能比匿名强,但是因为元组是值类型,如果经常赋值拷贝的话那么肯定是引用类型更好,所以匿名类型这时候才是用武之地。

下一节查询表达式,也是linq的终章。后面一张就是异步(并行和并发),这个考虑在汇编系列之后,因为介绍task实现原理,需要用到il,用到il就需要一些汇编知识。

重学c#系列——linq(3) [二十九]的更多相关文章

  1. Web 开发人员和设计师必读文章推荐【系列二十九】

    <Web 前端开发精华文章推荐>2014年第8期(总第29期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  2. 《手把手教你》系列技巧篇(二十九)-java+ selenium自动化测试- Actions的相关操作上篇(详解教程)

    1.简介 有些测试场景或者事件,Selenium根本就没有直接提供方法去操作,而且也不可能把各种测试场景都全面覆盖提供方法去操作.比如:就像鼠标悬停,一般测试场景鼠标悬停分两种常见,一种是鼠标悬停在某 ...

  3. 重学c#系列——字典(十一)

    前言 重学c#系列继续更新,简单看一下字典的源码. 看源码主要是解释一下江湖中的两个传言: 字典foreach 顺序是字典添加的顺序 字典删除元素后,字典顺序将会改变 正文 那么就从实例化开始看起,这 ...

  4. FreeSql (二十九)Lambda 表达式

    FreeSql 支持功能丰富的表达式函数解析,方便程序员在不了解数据库函数的情况下编写代码.这是 FreeSql 非常特色的功能之一,深入细化函数解析尽量做到满意,所支持的类型基本都可以使用对应的表达 ...

  5. Bootstrap <基础二十九>面板(Panels)

    Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素添加 class .panel 和 class .pa ...

  6. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】原创教程连载导读【连载完成,共二十九章】

    前言: 无数昼夜的来回轮替以后,这本<驱动篇I>终于编辑完毕了,笔者真的感动到连鼻涕也流下来.所谓驱动就是认识硬件,还有前期建模.虽然<驱动篇I>的硬件都是我们熟悉的老友记,例 ...

  7. 使用Typescript重构axios(二十九)——添加baseURL

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  8. 剑指Offer(二十九):最小的K个数

    剑指Offer(二十九):最小的K个数 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baid ...

  9. WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

    原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...

  10. VMwarevSphere 服务器虚拟化之二十九 桌面虚拟化之安装View副本服务器

    VMwarevSphere 服务器虚拟化之二十九  桌面虚拟化之安装View副本服务器 VMware View中高可用性可是一个必须要考虑的问题.在整个虚拟桌面环境中View Connection S ...

随机推荐

  1. DirectX 使用 Vortice 从零开始控制台创建 Direct2D1 窗口修改颜色

    本文将告诉大家如何使用 Vortice 底层库从零开始,从一个控制台项目,开始搭建一个最简单的使用 Direct2D1 的 DirectX 应用.本文属于入门级博客,期望本文能让大家了解 Vortic ...

  2. 前端程序员学习 Golang gin 框架实战笔记之一开始玩 gin

    原文链接 我是一名五六年经验的前端程序员,现在准备学习一下 Golang 的后端框架 gin. 以下是我的学习实战经验,记录下来,供大家参考. https://github.com/gin-gonic ...

  3. TomCat之安装

    TomCat 之安装(伪分布式版本) 本次安装是使用的伪分布式的安装(即一台机器安装两个tomcat) 1.通过scp导入tomcat安装包 2.解压缩成俩个文件 3.修改第一个tomcat的配置文件 ...

  4. Springboot+vue 实现汽车租赁系统(毕业设计二)(前后端项目分离)

    文章目录 1.系统功能列表 2.管理员端界面 2.1 商家登录界面 2.2 用户信息管理界面 2.3 汽车管理界面 2.4 订单界面 2.5 汽车图形报表 2.6 优惠券新增界面 3.普通用户界面 3 ...

  5. 使用dotnet-monitor sidecar模式 dump docker运行的dotnet程序.

    前情概要 随着容器和云技术的发展, 大量的应用运行在云上的容器中, 它们的好处是毋庸置疑的, 例如极大的提高了我们的研发部署速度, 快速的扩缩容等等, 但是也存在一些小小的问题, 例如难以调试. 基于 ...

  6. Blog2:nchu-software-oop-2022-4+5+期中

    Blog2:nchu-software-oop-2022-4+5+期中 一.前言 两次大作业是关于四边形和五边形的相关操作,类似于之前的三角形,但由于图形边数的变化,难度大大增加.对数学知识的运用考察 ...

  7. 怎么样子盒子能撑起父盒子?浮动,BFC,边距重叠

    怎么样子盒子能撑起父盒子? 从行内元素跟块元素来看: 一般情况下,行内元素只能包含数据和其他行内元素. 而块级元素可以包含行内元素和其他块级元素. 块级元素内部可以嵌套块级元素或行内元素. 建议行内元 ...

  8. Python基础之模块:4、正则表达式和re模块

    目录 一.正则表达式 1.正则表达式前戏 2.字符组 3.特殊符号 4.量词 5.贪婪匹配与非贪婪匹配 6.转义符 7.正则表达式实战 二.re模块 1.模块导入 2.常见操作方法 1.findall ...

  9. BERT模型源码解析

    BERT模型源码解析 modeling.py 目录 属性 类 class BertConfig(object)   BERT模型配置参数类 class BertModel(object)   BERT ...

  10. Linux网络通信(线程池和线程池版本的服务器代码)

    线程池 介绍 线程池: 一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线程的 ...