C#Linq技术中SelectMany(...)函数的内部实现的伪代码
我们先来假设这种场景:
一个学校中有多个年级,一个年级有多个班级,一个班级里有多个学生。这里我们只需要班级、年级、和学生这三个概念;
让我们先来定义Class类和Student类:
// 注意,Class是班级而不是 教室的意思,教室是 Classroom。
public class Class
{
public int ClassId { get; set; }
// 同一个班级的学生必然是属于同一个年级的,故GradeId直接在Class中声明就可以了。
public int GradeId { get; set; }
public List<Student> Students { get; set; }
} public class Student
{
public int StudentId { get; set; }
// 外键 ClassId
public int ClassId { get; set; }
public string OtherProp{ get; set; }
// 注意,学生没有GradeId属性
}
现在来声明多个班级:
List<Class> classes = new List<Class>();
classes.AddRange(...); // 这里添加的Class是有属于不同年级的
现在来看SelectMany(...);函数的声明:
声明一:
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);
声明二:
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
对于第一个声明:我们调用该函数的形式即为:
classes.SelectMany(cls=>cls.Students); // 这里很重要的一点,Func<TSource,IEnumerable<TResult>>里面的不是参数,而是类型,Func中最后一个泛型一定是返回值的泛型类型
// 这里classes 就是函数原型声明中的 source,而TSource就是Class类型,TResult就是 Student类型;而对于委托参数 selector中的 IEnumerable<TResult>实际上就是当前cls
// 代表的班级的所有学生,直接用cls.Students即可(而不是说自己声明一个 IEnumerable<Student> studs,然后将studs传到Func中,该Func只有一个参数)。
如上所示的代码实际上就是将多个班级classes中的所有学生都选出来返回一个 IEnumerable<Student> students,但是这里会存在一个问题,就是students中的学生
是classes中的学生总和,但是这时候我们无法知道students中某学生所属的年级是哪个了,如果想在返回classes中所有学生的集合的同时,对Student删减一些属性和
增加GradeId属性,这时候可以用第二个声明的SelectMany(..)函数,调用方法如下:
// 这里 cls就是声明二中的对应第一个委托Func的参数,TSource就是Class类型,cls.Students即是IEnumerable<TCollection>类型返回值,TCollection就是Student类型
// 而stud 就是cls.Students中的某一个元素,new{....}返回的类型是匿名类型,就是 TResult类型。
classes.SelectMany(cls=>cls.Students,(cls,stud)=>new{
ClassId=stud.ClassId,GradeId=cls.GradeId,StudentId=stud.StudentId}); // 这里的属性的增减 形式是随自己需要来改变的,不一定就是要这样
这时候返回的 IEnumerable<TResult> ches变量就是 对原来的Student进行了属性增减后的新类型(匿名类型'a)的集合,ches集合的元素个数和之前
classes.SelectMany(cls=>cls.Students)返回的元素个数是一样的。这时候要遍历ches 就不能用具体类型,只能用XXX(var itm in ches) 了。
现在来看看第二个声明的SelectMany(...)的内部实现的一种方式及其伪代码:
// TResult对应 'a匿名类型;TSource对应Class类型;TCollection对应Student类型
// source 对应classes
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{
IEnumerable<TResult> listResult = new IEnumerable<TResult>();
// source 对应 classes
foreach(var cls in source)
{
// TCollection对应Student,blockStudents对应 当前班级 cls中的所有学生集合
// 给collectionSelector传 Lambda表达式时给出了该委托承载的 函数的具体声明 cls=>cls.Students。
// Lambda表达式产生的 匿名函数的 参数类型,返回值类型一定是已知的,这里是Class和IEnumerable<Student>
IEnumerable<TCollection> blockStudents = collectionSelector(cls); /* 如果是第一个声明,那么这时候就会开始执行 listResult.AddRange(blockStudents);此时Student即是TResult*/ foreach(var stud in blockStudents) // 注意,这是第二层 foreach
{
// resultSelection(cls,stud) 返回的是 TResult,即匿名类型 'a 的实体对象,并添加到 listResult中
// resultSelection承载的Lambda表达式为:(cls,stud)=>new {ClassId.......GradeId...} ;new出的
// 匿名对象即为 TResult 类型。
listResult.Add(resultSelection(cls, stud));
} // Second Foreach End
} // First Foreach End
return listResult;
} // SelectMany(...) End
C#Linq技术中SelectMany(...)函数的内部实现的伪代码的更多相关文章
- C#Linq技术中SelectMany(...)的内部实现推测
对于声明为:public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable&l ...
- C++中的多态与虚函数的内部实现
1.什么是多态 多态性可以简单概括为“一个接口,多种行为”. 也就是说,向不同的对象发送同一个消息, 不同的对象在接收时会产生不同的行为(即方法).也就是说,每个对象可 ...
- Android逆向之旅---基于对so中的函数加密技术实现so加固
一.前言 今天我们继续来介绍so加固方式,在前面一篇文章中我们介绍了对so中指定的段(section)进行加密来实现对so加固 http://blog.csdn.net/jiangwei0910410 ...
- 改变JavaScript中函数的内部this指向!
改变JavaScript中函数的内部this指向! 第一种方法 call call 可以 调用函数 + 改变函数内的this指向! var obj = { name: 'lvhang' } funct ...
- [SAP ABAP开发技术总结]日期函数
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 《APUE》中的函数整理
第1章 unix基础知识 1. char *strerror(int errnum) 该函数将errnum(就是errno值)映射为一个出错信息字符串,返回该字符串指针.声明在string.h文件中. ...
- 【PHP】最详细PHP从入门到精通(二)——PHP中的函数
PHP从入门到精通 之PHP中的函数 各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持.PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新 ...
- 浅谈Kotlin中的函数
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/UV23Uw_969oVhiOdo4ZKAw作者:连凌能 Kotlin,已经被Android官方 ...
- 《python解释器源码剖析》第12章--python虚拟机中的函数机制
12.0 序 函数是任何一门编程语言都具备的基本元素,它可以将多个动作组合起来,一个函数代表了一系列的动作.当然在调用函数时,会干什么来着.对,要在运行时栈中创建栈帧,用于函数的执行. 在python ...
随机推荐
- jq 时间计算
-(function($){ var caculation = function(gap){ var minutes = 1000 * 60 var hours = minutes * 60 var ...
- Python 简单socket模拟ssh
OSI七层模型(Open System Interconnection,开放式系统互联) 应用层 表示层 回话层 传输层 tcp,udp 网络层 ip,icmp 数据链路层 mac地址 物理层 物理网 ...
- RecyclerView.ItemDecoration
decoration 英文意思: 英[ˌdekəˈreɪʃn] 美[ˌdɛkəˈreʃən] n. 装饰品; 装饰,装潢; 装饰图案,装饰风格; 奖章; [例句]The decoration and ...
- MySQL分类表设计--根据ID删除全部子类
在做数据库分类表的时候,通常会有这样的设计:一个字段是ID,另一个字段PID,PID指向自己的上级分类: 这样的设计带来的问题是:我要删除一个类,我希望它的子类全部一起删除: 在不知道分类有多少层级的 ...
- 杭电ACM——自我强化步骤
第一阶段:开始入门吧!(15天,53题) http://blog.csdn.net/always2015/article/details/44966019#t0 一.输入输出练习(2天,10题) 10 ...
- python利用scrapy框架爬取起点
先上自己做完之后回顾细节和思路的东西,之后代码一起上. 1.Mongodb 建立一个叫QiDian的库,然后建立了一个叫Novelclass(小说类别表)Novelclass(可以把一级类别二级类别都 ...
- 崩溃 golang入坑系列
早上(11.30)收到邮件,Vultr东京机房网络故障.当时搭建SS时,考虑到了机房故障.所以特意分出了日本和香港两条线路.但千算万算,忘记数据库还在东京机房中. 现在网络故障,SS服务器无法读取数据 ...
- 问题记录-运行Tomcat,项目程序没有响应
问题描述:运行Tomcat,项目程序没有响应原因在于 修改成一致路径即可解决.
- 51Nod 1090 3个数和为0 set 二分优化
给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等.从中找出所有和 = 0的3个数的组合.如果没有这样的组合,输出No Solution.如果有多个,按照3个数中最小的数从小到 ...
- php简单实现发微博动态
首先,肯定是注册成为开发者新浪微博开放平台 选择网站应用,填写一些基本信息 填完后在'我的应用'中,会看到刚创建的应用信息,我们只是简单的测试一下,所以其他复杂的注册信息都不用填写,有这些就够了 很重 ...