C#Linq技术中SelectMany(...)的内部实现推测

对于声明为:public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);而言,调用它的形式就是: AList.SelectMany(itm=>itm.listProp);  // 其中AList中的属性里有 也是集合的 属性listProp。listProp集合元素类型是TResult。

对于 AList.Select(itm=>itm.listProp)返回的是 IEnumerable<List<TResult>>

现在对于声明为:public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);

// TResult 中的字段 可以由 TSource和TCollection一起构成,当然也可以只 由TCollection的某些字段单独构成。

// 可以 假设:Class中有GradeId和ClassId字段和 List<Student> studs,而Student只有ClassId没有GradeId;那么

// IEnumerable<TSource>就是 Class的集合。 而 IEnumerable<TCollection>就是 Class中 Student的集合。

// 这时候调用 SelectMany的形式就是 classes.SelectMany(class=>class.studs,(class,stud)=>new{GradeId=class.GradeId,StudentId=stud.StudentId,...});

// 其中 classes就是 source, stud则是 studs中的元素。且如果方法中出现了两个委托参数,一般而言第二个委托需要间接用到第一个委托的返回值。

// 这个例子就说明了,为什么第二个委托里需要传 class。

 1      // 调用的时候是 source.SelectMany(i=>i.listProp,(i,s)=>...); i就是下面的itm       // TSource就类似Class;TCollection就类似 Student; TResult则是 第二个委托的返回值的 类型,可以是匿名类型
 2         public IEnumerable<TResult> SelectMany<TSource,TCollection,TResult>(source,collectionSelector,resultSelector)
 3         {
 4             IEnumerable<TResult> listResult = new IEnumerable<TResult>();         // source就类似上面的 classes
 5             foreach(var itm in source)
 6             {
 7                 // collectionSelector(itm)返回的是 itm.listProp;
 8                 // itm.listProp的类型 就是 TCollection 类型。
 9                 IEnumerable<TCollection> blockCollection = collectionSelector(itm);  // blockCollection类似某class 的studs
10                 // 如果没有后面的 resultSelector那么这时候实际上会执行 listResult.AddRange(blockList);
11
12                // IEnumerable<TResult> blockResult=new List<TResult>
13                 foreach(var citm in blockCollection)// 类似上面的studs
14                 {
15                     // 这里之所以用到 itm 是因为 TResult 中的字段未必都是 citm 里进行了删减,而还包括一些扩增,扩增的
16                     // 字段就可以是 itm中的。 举个栗子: itm是 Trade(有多个Order,即是 blockCollection),而 citm则是 Order,
17                     // 那么这时候返回的 Result未必 是 Order的属性缩减后得到的新的 对象,还可以是 itm中除了 blockCollection属性外的
18                     // 其它属性,例如收货人姓名 和 Order中的属性进行拼接。(注意,Order之前是没有收货人姓名的,因为一个 Order必然是
19                     // 属于一个具体的 Trade,而一个Trade是由一个 买家购买物品产生的,故只需要在 Trade中有收件人姓名即可。这里我们
20                     // 将收件人姓名这个属性 整合到了 Order中形成   ‘Order  ,即 TResult。
21                     // 所以说,之前觉得 itm是没必要的是因为自己没有搞懂 这个SelectMany的功能。总以为 对一个结构进行修改形成新的
22                     // 结构只是说 对原来的结构进行 修剪, 现在才知道,实际上还可以 对原来的结构进行 增加,而用什么增加,既可以是
23                     // 无关的数据,也可以是该结构的上级的数据。
24                     listResult.Add(resultSelection(itm, citm));  // resultSelection(itm,citm)的返回值就是 TResult 对象
25                 }
26             }
27             return listResult;
28         }
时间: 2024-10-04 15:33:33

C#Linq技术中SelectMany(...)的内部实现推测的相关文章

Linq技术四:动态Linq技术 -- Linq.Expressions

前面介绍了Linq的三个方面应用:Linq to SQL, Linq to XML和Linq to Object,这篇介绍一下动态Linq的实现方式及应用场景. 命名空间: System.Linq; System.Linq.Expressions; 应用Linq的时候,我们都知道只需要Lambda表达式就行,但有些场景仅仅只使用Data Model的字段名操作是不够的或者不方便的. 场景1:假设我们需要拼接Where条件进行查询,一种方式可以拼接IQueryable的表达式.但我想像写SQL语句

编写高质量代码改善C#程序的157个建议——建议29:区别LINQ查询中的IEnumerable&lt;T&gt;和IQueryable&lt;T&gt;

建议29:区别LINQ查询中的IEnumerable<T>和IQueryable<T> LINQ查询一共提供了两类扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展:Queryable类,它针对继承了IQueryable<T>接口的集合类进行扩扎.接口IQueryable<T>也是继承了IEnumerable<T>接口的,所以,致使两个接口的方

【LINQ技术】扩展特性和LINQ操作符

LINQ特有的编程结构 LINQ就像是嵌入到C#中的强类型查询语言,尽管和SQL查询很像,但语法却并不相同,甚至还有截然相反的一面. LINQ是在.NET发展到3.5版的时候被引进的,C#和VB语言都为此做了许多工作,扩展了大量新的编程结构. 一.隐式类型本地变量 var--一个如此小巧的关键字却有着强大的力量. var varInt=1; var varBool=True; var varString="String, String, String"; Console.WriteLi

Linq技术

第一次课 框架技术:基本功能封装好,程序员直接使用     分类:    数据访问层框架(简化数据访问)    业务层框架    表示层框架 ORM:object对象与关系relation映射Mapping,数据访问层框架技术    Linq to sql    EF 实体模型    NHbinate等    baits等    ...  //前提:每一个表必须有主键  //在项目新建ADO.net实体对象模型,自动生成访问操作的上下文入口,  及实体类. 1获取所有数据代码1:     //定

《自动化技术中的进给电气运动》及学科学习笔记二

<自动化技术中的进给电气运动> 阅读内容:第1.3节 知识要点: 本节主要以不可调节电气传动系统为例,介绍了系统在时间域的静态和动态特性以及电气系统对于简单信号的响应. 1.采用微分方程分析系统 对于只有一个输入和输出的线性系统都可表示成如下的微分方程形式.其中u为输入,v为输出,且对于实际系统有m≤n. 以不可调电气传动系统为例,列出系统的机械和电气微分方程. (1)JGes=JM+JL (2)uA-eM=RAiA+LAdiA/dt (3)eM=cMωM (4)MM=ML+MB=ML+JGe

自动化技术中的进给电气传动研习笔记-1

1.调节技术基础 1.1术语和概念 1.1.1控制和调节 本节主要介绍的为控制和调节的联系.控制的核心特征是开环作用路径,即控制链路,换句话说就是输入量单方向决定了输出量.而调节的核心特征是闭环,即调节回路,强调反向作用和比较,输出了不断影响自身.同时为我们提供了控制调节系统的表达方式,即工作原理框图.而系统的静态特性和动态特性却存在着巨大的不同,静态特性表现为函数图线,而动态特性需要过渡函数或微分方程进行表达. 1.1.2调节回路型号 调节型号分为模拟信号,数字信号和二进制信号.这里尤其需要在

在Activity中响应ListView内部按钮的点击事件

最近交流群里面有人问到一个问题:如何在Activity中响应ListView内部按钮的点击事件,不要在Adapter中响应? 对于这个问题,我最初给他的解答是,在Adapter中定义一个回调接口,在Activity中实现该接口,从而实现对点击事件的响应. 下班后思考了一下,觉得有两种方式都能比较好的实现:使用接口回调和使用抽象类回调. 正好可以复习一下接口和抽象类的区别,于是写了两个Demo: 1.使用接口回调: Adapter类 1 package com.ivan.adapter; 2 3

Xen虚拟化技术中PV和HVM的区别

转自 这里 Xen是一个开源的type-1或者裸机管理程序,它使得一个物理主机能够同时并行运行多个相同的或者不同的操作系统实例.Xen是目前唯一的开源可得的type-1管理程序.Xen被应用于许多商业和开源的应用程序中,比如:服务器虚拟化(server virtualization).基础设施即服务(Infrastructure as a Service).桌面虚拟化(desktop virtualization).安全应用程序(security applications).嵌入式和硬件设备(e

#前端杂谈 【Web 建站技术中,HTML、HTML5、XHTML、CSS、SQL、JavaScript、PHP、ASP.NET、Web Services 是什么?via知乎 张秋怡】

先附上链接:Web 建站技术中,HTML.HTML5.XHTML.CSS.SQL.JavaScript.PHP.ASP.NET.Web Services 是什么? 这是分享自知乎用户张秋怡的一个回答,用通俗形象的语言解释了关于前端的一些基本概念,比较适合像我这种刚入门的小白阅读.