在平时开发中经常会看到有些朋友或者同事在写代码时会充斥着各种for,foreach,这种程式代码太多的话阅读性特别差,而且还显得特别累赘,其实在FCL中有很多帮助我们提高阅读感的方法,而现实中很多人不会用或者说不知道,这篇我就跟大家聊一聊。

一:SelectMany

这个方法绝对是提高开发速度的一大利器,有太多的业务场景需要使用这个函数,举一个我实际应用场景,商家按照年份和客户类型预先设置一些标签,然后让系统跑一下它的各自标签到底有多少人?

1. 定义Model

为了方便演示,这里做了一下简化代码,只有一个字典,key表示年份,value:就是该年份的多组标签。

public class EstimateModel{public int ShopID { get; set; }//key:年份public Dictionary<string, List<TagCrowdFilterModel>> YearCrowdFilterDict { get; set; }}public class TagCrowdFilterModel{/// <summary>/// 筛选条件/// </summary>public string CrowdFiter { get; set; }/// <summary>/// 获取人数/// </summary>public int TotalCustomerCount { get; set; }}

为了更加清晰,我决定再填充一下数据

        public static void Main(string[] args){var estimateModel = new EstimateModel(){ShopID = 1,YearCrowdFilterDict = new Dictionary<string, List<TagCrowdFilterModel>>(){{"17年",new List<TagCrowdFilterModel>(){new TagCrowdFilterModel(){ CrowdFiter="between 10 and 20" },new TagCrowdFilterModel(){ CrowdFiter=" a<10  || a>30" },}},{"18年",new List<TagCrowdFilterModel>(){new TagCrowdFilterModel(){ CrowdFiter="between 100 and 200" },new TagCrowdFilterModel(){ CrowdFiter=" a<100  || a>300" },}},{"19年",new List<TagCrowdFilterModel>(){new TagCrowdFilterModel(){ CrowdFiter="between 1000 and 2000" },new TagCrowdFilterModel(){ CrowdFiter=" a<1000  || a>3000" },}}}};}public static int GetCustomerID(string crowdfilter){return BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);}

2. 实现需求

需求也很简单,就是依次获取 TagCrowdFilterModel 中的 CrowdFiter 字段再调用GetCustomerID方法把人数赋值给TotalCustomerCount即可,这么简单的需求,如果让你来搞定,你该怎么实现这个逻辑?没错,很多人可能就是两个foreach搞定。

        foreach (var year in estimateModel.YearCrowdFilterDict.Keys){var yearCrowdFitlerList = estimateModel.YearCrowdFilterDict[year];foreach (var crowdFitler in yearCrowdFitlerList){crowdFitler.TotalCustomerCount = GetCustomerID(crowdFitler.CrowdFiter);}}

看似代码也很清爽,但现实哪有这么好的事情,真实情况是年份上可能还要套上一个客户类型,客户类型之上再套一个商品,商品之上再套一个商家,这样很深的层级你就需要多达3个foreach,4个foreach甚至5个foreach才能搞定,再放张图给大家看看,是不是看着头大...????

3. 优化办法

如果你会selectMany,那只需要一个链式写法就可以搞定,是不是简单粗暴,虽然性能比不上命令式写法,但可读性和观赏性真的上了几个档次。

            estimateModel.YearCrowdFilterDict.SelectMany(m => m.Value).ToList().ForEach(m =>m.TotalCustomerCount = GetCustomerID(m.CrowdFiter));

二:原理探究

1. msdn解释

将序列的每个元素投影到 IEnumerable,并将结果序列合并为一个序列,并对其中每个元素调用结果选择器函数,链接:https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.selectmany?view=netframework-4.8 有了上面的案例解释,再看msdn的这句话,我想你应该彻彻底底的明白了selectMany怎么使用。

2. 翻查源码

宏观上明白了,接下来用ILSpy去查下微观代码,到底这玩意是怎么实现的。

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{if (source == null){throw Error.ArgumentNull("source");}if (selector == null){throw Error.ArgumentNull("selector");}return SelectManyIterator(source, selector);
}private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{foreach (TSource item in source){foreach (TResult item2 in selector(item)){yield return item2;}}
}

大家仔细体会下这两个foreach,尤其是第二个foreach,其中的selector(item)不就是年份下的标签集合吗?再遍历这个集合把每一个item返回出去,返回值是IEnumerable,这得益于yield语法糖,它本质上就是一个编译器封装好的迭代类,做到了一个延迟,按需执行,后面我会专门分享一下yield,很有意思????

好了,本篇就说到这里,希望对你有帮助。

Linq下有一个非常实用的SelectMany方法,很多人却不会用相关推荐

  1. 一个Spring AOP的坑!很多人都犯过!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 很多读者看完之后表示用起来很爽,但是后台也有人留言说自己配 ...

  2. linux下限制一个文件夹大小的方法

    linux上有时由于一些特殊的用途,我们需要限制一个文件夹的大小.核心方法都是把需要限制的文件夹挂载在一个大小固定的分区上,下面有两种方法可以实现: 使用ramdisk linux可以把一部分内存mo ...

  3. plusready html5,封装一个简单实用的 plusready 方法

    如果有小伙伴看过 mui.js 的源码的话,对于以下代码就不会陌生. var plusReady = function (callback) { if (window.plus) { callback ...

  4. windows 7下如何卸载重装mysql 压缩包版百度经验_windows下安装、卸载mysql服务的方法(mysql 5.6 zip解压...

    MySQL是一个小巧玲珑但功能强大的数据库,目前十分流行.但是官网给出的安装包有两种格式,一个是msi格式,一个是zip格式的.很多人下了zip格式的解压发现没有setup.exe,面对一堆文件一头雾 ...

  5. python命令行tab补全_python命令行下按tab建补全的方法

    此方法只在centos6上测试通过,其它系统木有测试 1.在用户家目录下创建一个名字叫 .pythonstartup 的隐藏文件,写入如下内容: # python startup file impor ...

  6. 很多人都想考一个RHCE吧,大家不妨看看我是怎么变成一个RHCE的。

    从CHINAUNIX上看到的文章,很有感慨,一个学计算机的同学的经历,在河南这个地方,很多同学毕业,都不干计算机相关的工作,看看人家的酸甜苦辣吧. http://bbs.chinaunix.net/t ...

  7. mysql5.6解压包卸载_windows下安装、卸载mysql服务的方法(mysql 5.6 zip解压版安装教程)...

    MySQL是一个小巧玲珑但功能强大的数据库,目前十分流行.但是官网给出的安装包有两种格式,一个是msi格式,一个是zip格式的.很多人下了zip格式的解压发现没有setup.exe,面对一堆文件一头雾 ...

  8. mysql安装卸载服务_windows下安装、卸载mysql服务的方法(mysql 5.6 zip解

    MySQL是一个小巧玲珑但功能强大的数据库,目前十分流行.但是官网给出的安装包有两种格式,一个是msi格式,一个是zip格式的.很多人下了zip格式的解压发现没有setup.exe,面对一堆文件一头雾 ...

  9. Aveiconifier是一个非常实用方便的制作ico格式文件的小工具~

    本文地址:http://www.jb51.net/article/8314.htm Aveiconifier是一个非常实用方便的制作ico格式文件的小工具~ 也许有一些对网页知识不是很了解的网友并不清 ...

最新文章

  1. URL化 替换空格
  2. 2.2.6 学习率衰减
  3. OpenCV与gcc和CMake一起使用
  4. 我的log4net使用手册(转自 http://blog.csdn.net/lyjcn/archive/2009/08/11/4432833.aspx)
  5. Java中构造函数,静态代码块,构造代码块的执行顺序
  6. Unity3D之UGUI基础6:Slider滑条
  7. 学习使用Ansj分词工具(一)
  8. java中equals以及==的用法(简单介绍)
  9. git 修改commit内容(--amend)
  10. 淘宝API接口调用:item_search_img - 按图搜索淘宝商品(拍立淘)
  11. Android TextView 文字设置不同字体大小和颜色样式
  12. 动态注册 Module
  13. services.msc 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动
  14. 微信小程序cover-image手机上不显示问题
  15. 【渝粤教育】广东开放大学 证券投资学 形成性考核 (1)
  16. 网页播放器看视频页面绿屏解决方法
  17. STM32蜂鸣器实例详解
  18. Linux 私房菜————Linux系统基本操作命令(十)|引导程序|服务控制
  19. Android 仿微博列表视频(一),静音播放
  20. 电脑开机CPU被Windows资源管理器占满,导致其他软件不可用解决方法

热门文章

  1. mysql按月进行表分区
  2. ASP.NET登录以及注册
  3. StackExchange.Redis 使用 (一)
  4. Html、Css-----当有文字和图片的时候,需要文字和图片居中,怎么实现?不想文字换行怎么设置...
  5. 在Windows Live Writer中插入C# code
  6. [转]Myeclipse9引入easy_ui时,其中的部分js文件报错
  7. 带有控制按钮的图片滚动
  8. IBM软件OEM概览
  9. COM组件与.NET技术对比
  10. 把我的爱送给你――C#3.5(这题目似乎写错了)