【温故知新】C# Linq中 Select SelectMany 使用技巧

微信公众号:趣编程ACE
关注可了解更多的.NET日常实战开发技巧,如需源码 后台回复 源码 即可;
如果觉得对你有帮助,欢迎关注

C# Linq中 Select && SelectMany 使用技巧

Select 和 SelectMany 是我们开发中对集合常用的两个扩展方法,今天我就用几个小例子并结合源码形式展示下这两个方法的使用形式。


前文回顾

【温故知新】C# Linq中 Where使用技巧

Select 的基本使用

首先我创建一个Student的类,类的结构如下:

1   public class Student2    {3        public int Id { get; set; }  // 学生ID4        public string Name { get; set; } // 学生姓名5        public List<string> Programing { get; set; } // 学生掌握的 编程语言678        // 获取学生集合9        public static List<Student> GetStudents()
10        {
11            return new List<Student>()
12            {
13                new Student
14                { 
15                    Id = 1, 
16                    Name ="张三",
17                    Programing = new List<string>
18                    {
19                        "C#","Java","JS"
20                    }
21                },
22                new Student
23                {
24                    Id=2,
25                    Name ="李四",
26                    Programing=new List<string>
27                    {
28                        "C++","C","Node.js"
29                    }
30                },
31                 new Student
32                {
33                    Id=3,
34                    Name ="王五",
35                    Programing=new List<string>
36                    {
37                        "Sql","C","Node.js"
38                    }
39                },
40                new Student
41                {
42                    Id=4,
43                    Name ="赵六",
44                    Programing=new List<string>
45                    {
46                        "MVC","C","Node.js"
47                    }
48                },
49            };
50        }
51
52    }

然后在Main函数中调用GetStudents方法,并对集合使用Select方法

1// 因为Id是int 类型 将集合里面所有子项的Id组合起来 变成一个新集合
2// 所以返回值是 IEnumerable<int> 类型
3IEnumerable<int> ids = Student.GetStudents().Select(s => s.Id);  
4foreach (var item in ids)
5{
6  Console.WriteLine(item); // 输出 1,2,3,4
7}

那么对于这个Select方法,內部源码是怎么实现的呢?

1// F12 进入查看源码结构
2// 返回值是 IEnumerable<TResult> 类型
3// 是所有 IEnumerable<TSource> source 类型的扩展方法
4// 一个入参 Func<TSource, TResult> selector 的内置委托 其中 委托入参是TSource 类型,返回值是TResult类型
5public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)

手写Select源码实现:

1public static IEnumerable<TResult> SelectExtension<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)2{3  if(source == null) throw new ArgumentNullException("source");4  if(selector == null) throw new ArgumentNullException("selector");56  foreach (var item in source)7  {8    yield return selector(item);9  }
10}

SelectMany 的基本使用

1.在上文定义的Student类中,我们要拿到所有人会的编程语言,那么就可以通过SelectMany实现。

1var stus = Student.GetStudents().SelectMany(s => s.Programing);
2foreach (var item in stus)
3{
4   Console.WriteLine(item);
5}

470c9bf4ede881629d522a06d09b407a.png


那么这个方法中SelectMany的作用是什么呢?
SelectMany 将序列(也就是Student的集合)的每个元素投影到IEnumerable上,这样就将其转化为一个IEnumerable类型的数据。也就是说SelectMany 这个方法将一系列结果组合在一起变成一个新的结果。
以下便是SelectMany的一个重载源码实现:

1// 返回值是 IEnumerable<TResult> 类型2// 是所有 IEnumerable<TSource> source 类型的扩展方法3// 一个入参 Func<TSource, IEnumerable<TResult>> selector 类型的内置委托 4// 其中委托函数需要一个Tsource类型的参数,返回值是IEnumerable<TResult>> 类型5public static IEnumerable<TResult> SelectManyExtension<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)6{7  if(source == null) throw new ArgumentNullException("source");8  if(selector == null) throw new ArgumentNullException("selector");9   return SelectManyExtensionIterator(source, selector);
10}
11//SelectManyExtensionIterator 迭代实现
12static IEnumerable<TResult> SelectManyExtensionIterator<TSource, TResult>(IEnumerable<TSource> source,
13Func<TSource, IEnumerable<TResult>> selector)
14{
15   foreach (var item in source)
16    {
17      foreach (var result in selector(item))
18       {
19         yield return result;
20       }
21    }
22}

2.要拿到每个学生姓名及其所会的编程语言?这就可以通过SelectMany方法的另一种重载来实现

1// 其中SelectMany 第一入参是一个内置委托:2  //入参为集合的元素类型,返回值是元素的一个集合类型(Student)3// 第二个参数也是一个内置委托: 4  //入参有两个,第一个为集合元素类型(Student),第二个为前面参数返回值的元素类型5  // 其中这个内置委托的返回值是一个TResult 类型,此处代码TResult 为new 出来的匿名类型6var stuInfo = Student.GetStudents().SelectMany(s => s.Programing,7                (stu, str) => new8                {9                    StudentName = stu.Name,
10                    PragramName = str
11                });
12foreach (var item in stuInfo)
13{
14  Console.WriteLine(item.StudentName+"=>"+item.PragramName);
15}

898053394161f18f577799b2debb2d97.png


那么这个SelectMany的重载源代码是怎么实现的呢?

1public static IEnumerable<TResult> SelectManyExtension2<TSource, TCollection, TResult>(this IEnumerable<TSource> source, 2            Func<TSource, IEnumerable<TCollection>> collectionSelector, 3            Func<TSource, TCollection, TResult> resultSelector)4        {5            if(source==null) throw new ArgumentNullException("source");6            if(collectionSelector == null) throw new ArgumentNullException("collectionSelector");7            if(resultSelector == null) throw new ArgumentNullException("resultSelector");89            return SelectManyExtensionIterator2<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
10        }
11
12
13        static IEnumerable<TResult> SelectManyExtensionIterator2<TSource, TCollection, TResult> (IEnumerable<TSource> source,
14            Func<TSource, IEnumerable<TCollection>> collectionSelector,
15            Func<TSource, TCollection, TResult> resultSelector)
16        {
17            foreach (var item in source)
18            {
19                foreach (var collection in collectionSelector(item))
20                {
21                    yield return resultSelector(item, collection);
22                }
23            }
24        }

具体演示看上文视频~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bzoj4870

http://www.lydsy.com/JudgeOnline/problem.php?id4870 矩阵快速幂。。。 人话题意&#xff1a;从nk个物品里选模k余r个物品&#xff0c;问方案数模P 那么我们有方程 f[i][j]f[i-1][j]f[i-1][j-1] 跟组合数一个样子 j∈(0,k) 这个物品选还是不选加起来 构造矩阵&#xff1a;x.…

Codeforces Round #410 (Div. 2) D. Mike and distribution 思维+数学

链接&#xff1a; http://codeforces.com/contest/798/problem/D 题意&#xff1a; 给你两个长度为n的数列a和b&#xff0c;让你选n/21个下标&#xff0c;使得2*∑ai>suma,2*∑bi>sumb 题解1&#xff1a; 用一个叫random_shuffle的东西&#xff0c;每次都乱选&#xff0c…

PerfView专题 (第三篇):如何寻找 C# 中的 VirtualAlloc 内存泄漏

一&#xff1a;背景 上一篇我们聊到了如何用 PerfView 去侦察 NTHeap 的内存泄漏&#xff0c;这种内存泄漏往往是用 C 的 malloc 或者 C 的 new 分配而不释放所造成的&#xff0c;这一篇我们来聊一下由 VirtualAlloc 方法造成的泄漏如何去甄别&#xff1f;了解 VirtualAlloc 的…

[APP]- 找回Xcode7的代码折叠功能

为什么80%的码农都做不了架构师&#xff1f;>>> 原 找回Xcode7的代码折叠功能 升级到Xcode7后&#xff0c;会发现代码折叠功能不见了&#xff0c;这是怎么回事&#xff1f; 其实这个功能还在的&#xff0c;只是苹果默认把这个功能禁掉了&#xff1a;在Xcode菜单里选…

HTML5程序开发范例宝典 完整版 (韩旭等著) 中文pdf扫描版

HTML5程序开发范例宝典紧密围绕编程者在编程中遇到的实际问题和开发中应该掌握的技术&#xff0c;全面介绍了利用HTML进行程序开发的各方面技术和技巧。全书共16章&#xff0c;内容包括HTML网页布局、HTML基本元素、HTML高级元素、表单的使用、列表的使用、超链接、表格应用、图…

ASP.NET Core 6框架揭秘实例演示[11]:诊断跟踪的几种基本编程方式

在整个软件开发维护生命周期内&#xff0c;最难的不是如何将软件系统开发出来&#xff0c;而是在系统上线之后及时解决遇到的问题。一个好的程序员能够在系统出现问题之后马上定位错误的根源并找到正确的解决方案&#xff0c;一个更好的程序员能够根据当前的运行状态预知未来可…

Autofac详解

Autofac详解 零、文章目录 一、Autofac详解 1、概述 Autofac是第三方IOC容器&#xff0c;是当前最流行的IOC容器。功能强大&#xff0c;比asp.netcore内置容器强大得多&#xff0c;支持属性注入和方法注入&#xff0c;支持AOP。官网地址&#xff1a;http://autofac.org/源码下载…

与ObjectDataSource共舞

4&#xff0c;ORM组件XCode&#xff08;与ObjectDataSource共舞&#xff09; XCode为了能更方便的解决大部分问题&#xff0c;不得不“屈身”于ObjectDataSource。 先上一个经典例子&#xff08;ObjectDataSourceGridView&#xff09;&#xff08;ObjectDataSource&#xff0…

ASP.NET Core 3.1中使用JWT身份认证

文章目录 0、引言1、关于Authentication与Authorization2、整个认证流程是怎样的&#xff1f;3、开始JWT身份认证 3.1 安装JwtBearer包3.2 安装Swashbuckle.AspNetCore包3.3 添加身份认证相关服务到容器中3.4 添加Swagger服务到容器中3.5 将身份认证加入到管道中3.6 将swagger加…

《ASP.NET Core 6框架揭秘》实例演示[10]:Options基本编程模式

依赖注入使我们可以将依赖的功能定义成服务&#xff0c;最终以一种松耦合的形式注入消费该功能的组件或者服务中。除了可以采用依赖注入的形式消费承载某种功能的服务&#xff0c;还可以采用相同的方式消费承载配置数据的Options对象&#xff0c;这篇文章演示几种典型的编程模式…

实现仿简书选取内容生成分享图片效果

前几天脑子里忽然闪过简书的图片分享效果&#xff0c;感觉很简洁也很漂亮&#xff0c;想着能不能用自己方式实现一下呢&#xff0c;于是今天就有了这篇文章。好了&#xff0c;先看下效果图吧&#xff1a; 项目地址: https://github.com/zhangke301... 欢迎star、issues~ 实现这…

千万级可观测数据采集器--iLogtail代码完整开源

2022年6月29日&#xff0c;阿里云iLogtail开源后迎来首次重大更新&#xff0c;正式发布完整功能的iLogtail社区版。本次更新开源全部C核心代码&#xff0c;该版本在内核能力上首次对齐企业版&#xff0c;开发者可以构建出与企业版性能相当的iLogtail云原生可观测性数据采集器。…

Java8新特性--CompletableFuture

并发与并行 Java 5并发库主要关注于异步任务的处理&#xff0c;它采用了这样一种模式&#xff0c;producer线程创建任务并且利用阻塞队列将其传递给任务的consumer。这种模型在Java 7和8中进一步发展&#xff0c;并且开始支持另外一种风格的任务执行&#xff0c;那就是将任务的…

用 MAUI 在Windows 和 Linux 绘制 PPT 图表

我在做一个图表工具软件&#xff0c;这个软件使用 MAUI 开发。我的需求是图表的内容需要和 PPT 的图表对接&#xff0c;需要用到 OpenXML 解析 PPT 内容&#xff0c;读取到 PPT 图表元素的内容&#xff0c;接着使用 MAUI 渲染层绘制图表元素。图表工具软件需要在 Windows 平台和…

聊聊接口性能优化的11个小技巧

前言 接口性能优化对于从事后端开发的同学来说&#xff0c;肯定再熟悉不过了&#xff0c;因为它是一个跟开发语言无关的公共问题。 该问题说简单也简单&#xff0c;说复杂也复杂。 有时候&#xff0c;只需加个索引就能解决问题。 有时候&#xff0c;需要做代码重构。 有时…

Java中ArrayList,LinkedList,Vector三者的异同点及其使用场景和ArrayList的一些常用方法

相同点&#xff1a;三者存储的都是有序&#xff0c;可重复的数据。 异&#xff1a; ①&#xff1a;ArrayList底层存储类型是Object数组&#xff0c;而LinkedList底层是双向链表 ②&#xff1a;ArrayList和Vector调用创建空参构造器创建对象时&#xff0c;默认的size是10&…

第二百四十六节,Bootstrap弹出框和警告框插件

Bootstrap弹出框和警告框插件 学习要点&#xff1a; 1.弹出框 2.警告框 本节课我们主要学习一下 Bootstrap 中的弹出框和警告框插件。 一&#xff0e;弹出框 弹出框即点击一个元素弹出一个包含标题和内容的容器。 基本用法 注意&#xff1a;必须在js结合popover()方法使用 da…

Intellij IDEA2017 的控制台里不识别maven命令问题处理

2019独角兽企业重金招聘Python工程师标准>>> cmd里运行 mvn -v可以显示出maven的版本信息&#xff0c;可是在IDEA的控制台里却提示不识别maven命令&#xff0c;此情况以管理员的身份运行IDEA即可。 转载于:https://my.oschina.net/u/2364025/blog/1788797

使用IDEA 提交代码到svn

2019独角兽企业重金招聘Python工程师标准>>> 新手第一次使用教程&#xff1a; 一、安装svn TortoiseSVN是个客户端&#xff0c;需要安装VisualSVN服务端。 二、IDEA配置&#xff08;Ctrl alt S&#xff09; 需要配置服务端svn.exe文件。 三、上传代码 svn路径&…

如何在 BackgroundService 获取 ASP.NET Core 启动地址

前言上次&#xff0c;我们介绍了《如何获取 ASP.NET Core 启动地址》。但是&#xff0c;如果要在 BackgroundService 中获取启动地址可不那么容易&#xff0c;因为 BackgroundService 在 app 启动前就开始执行了:var builder WebApplication.CreateBuilder(args); builder.Ser…