Linq 下的扩展方法太少了,您期待的 MoreLinq 来啦

一:背景

1. 讲故事

前几天看同事在用 linq 给内存中的两个 model 做左连接,用过的朋友都知道,你一定少不了一个叫做 DefaultIfEmpty 函数,这玩意吧,本来很流畅的 from...in...join, 突然搞进来这么一个函数,真的是恶心他妈给恶心开门,恶心到家了,简化后的代码如下:

class User{public int UserID { get; set; }public string Email { get; set; }}class Order{public int OrderID { get; set; }public string OrderTitle { get; set; }public int UserID { get; set; }}static void Main(string[] args){var userList = new List<User>(){new User(){ UserID=1, Email="333@qq.com"},new User(){ UserID=2, Email="444@qq.com"},};var orderList = new List<Order>(){new Order(){ OrderID=1, OrderTitle="订单1", UserID=1},new Order(){ OrderID=2, OrderTitle="订单2", UserID=1}};var query = from u in userListjoin o in orderList on u.UserID equals o.UserID into grpfrom item in grp.DefaultIfEmpty()select new { UserID = u.UserID, OrderTitle = item?.OrderTitle };       }    

之所以出现这个情况是因为不管是 查询关键词 还是 扩展方法,都并没有直接对 leftjoin 和 rightjoin 底层支持,只能通过变通的方式去实现,这就很尴尬了,比如说上面的这段代码,你很难在多天之后还能准确理解这里的 DefaultIfEmpty 是用来干嘛的,那现在问题的关键在于,有没有什么方法让底层支持或者有可信的第三方帮我封装好,还真巧,在 github 上 还真有一个 morelinq 项目:https://github.com/morelinq/MoreLINQ,看 md 是给 Enumerable 扩展了 60,70 个方法,如虎添翼呀,接下来一起来探索下吧。

二:MoreLinq 下的探索

1. 安装

安装非常简单,用 nuget 跑一下  Install-Package morelinq -Version 3.3.2 即可。

2. LeftJoin / RightJoin / FullJoin

在 morelinq 中就提供了 左外,右边,全连接,这就很????????了,提高开发效率,让我们更加专注业务,这里就使用 leftjoin 来改造刚才的代码,代码如下:

var query2 = userList.LeftJoin(orderList, u => u.UserID, o => o.UserID,u => new { UserID = u.UserID, OrderTitle = default(string) },(u, o) => new { UserID = u.UserID, OrderTitle = o.OrderTitle });

怎么样,一句链式就搞定了,而且代码还非常好理解。

  • 第一个参数:join 集合

  • 第二个参数:source 集合的关联 id

  • 第三个参数:join 集合的关联 id

  • 第四个参数:source 存在,join不存在 应该返回的 model 架构

  • 第五个参数:source,join 都存在      应该返回的 model 架构

刚才也说到了有60,70个扩展方法,大家可以去趴一趴其他有趣的东西,这里我推荐几个给大家演示一下,毕竟还是非常实用的。

3. Shuffle

从字面意思上看就是洗牌,挺实用的一个方法,很多时候我希望在一个集合中随机抽取一条记录,比如说我有10套邮件模板,当用户下订单之后,我希望可以随机抽一套模板给用户,以防被 qq邮箱 放入垃圾箱中,原来我需要是用 new guid 来实现,如下代码:

var list = new List<int>() { 1, 3, 5, 7, 9, 11, 12 };var query = list.OrderBy(m => Guid.NewGuid());Console.WriteLine(string.Join(",",query));---- output -----11,7,9,12,5,3,1

现在就简单多了,直接使用 Shuffle 搞定。

var list = new List<int>() { 1, 3, 5, 7, 9, 11, 12 };var query = list.Shuffle();Console.WriteLine(string.Join(",", query));----- output ------5,1,9,12,7,3,11

4.  Insert

有时候我需要在 IEnumerable 集合的指定位置插入一个集合,举个例子, A= { 1, 3, 5, 7, 9, 11, 12 }, B ={8}, 我希望将 8 插入到 7 和 9 之间,在现有的 Enumerable 下只有 Concat 和 Append 方法,无法做到指定插入,这个需求又可以被 moreqlinq 搞定啦。。。代码如下:

IEnumerable<int> list = new List<int>() { 1, 3, 5, 7, 9, 11, 12 };var query = list.Insert(new List<int>() { 8 }, 4);Console.WriteLine(string.Join(",", query));

可以看到往一个集合的指定位置插入一个集合就是这么轻松如意,太爽啦~~~

5. ForEach

不知道什么原因,至今在 IEnumerable 下都没有提供 ForEach 扩展方法,我这个升斗小民反正是体会不到这么设计的哲学在哪里,在原来你只能 ToList 立即执行,要么使用 foreach 进行延期遍历,现在就方便多了,简化的代码如下:

IEnumerable<int> list = new List<int>() { 1, 3, 5, 7, 9, 11, 12 };list.ForEach(m =>{Console.Write(m+" ");});

6. ToDataTable

对在看的各位大佬估计都用不上,对我们公司几个 10 + 年的项目,那是万万不能少哈,如有能用得上的,可以简单看一下:

非常简单,不过我还是好奇一下它是怎么做到的,可以用 ilspy 去翻翻它的源码:


public static TTable ToDataTable<T, TTable>(this IEnumerable<T> source, TTable table, params Expression<Func<T, object>>[] expressions) where TTable : DataTable
{MemberInfo[] members = PrepareMemberInfos(expressions).ToArray();members = BuildOrBindSchema(table, members);Func<T, object[]> func = CreateShredder<T>(members);table.BeginLoadData();try{foreach (T item in source){DataRow dataRow = table.NewRow();dataRow.ItemArray = func(item);table.Rows.Add(dataRow);}return table;}finally{table.EndLoadData();}
}private static IEnumerable<MemberInfo> PrepareMemberInfos<T>(ICollection<Expression<Func<T, object>>> expressions)
{if (expressions == null || expressions.Count == 0){return typeof(T).GetMembers(BindingFlags.Instance | BindingFlags.Public).Where(delegate(MemberInfo m){if (m.MemberType != MemberTypes.Field){PropertyInfo propertyInfo = m as PropertyInfo;if ((object)propertyInfo != null && propertyInfo.CanRead){return propertyInfo.GetIndexParameters().Length == 0;}return false;}return true;});}try{return expressions.Select(GetAccessedMember);}catch (ArgumentException innerException){throw new ArgumentException("One of the supplied expressions is not allowed.", "expressions", innerException);}MemberInfo GetAccessedMember(LambdaExpression lambda){Expression expression = lambda.Body;if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked){expression = ((UnaryExpression)expression).Operand;}MemberExpression memberExpression = expression as MemberExpression;if (memberExpression == null || memberExpression.Expression.NodeType != ExpressionType.Parameter){throw new ArgumentException($"Illegal expression: {lambda}", "lambda");}return memberExpression.Member;}
}

从上面源码大概可以看到,将 List 转成 DataTable 支持两种方式,要么反射,要么 Expression 解析树,默认用的是反射,性能要稍微低一点。

三:总结

当然这里还有很多的扩展方法,篇幅原因恕不能一一介绍,有兴趣的朋友可以pull下来试一试,总的来说这种工具类太棒了,让我们可以更好的专注于业务。

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

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

相关文章

紧跟月影大佬的步伐,一起来学习如何写好JS(上)

如何写好JS - 三大原则&#x1f302;序言一、☂️什么才是好的JS代码&#xff1f;二、&#x1f9f5; 写好JS的一些原则1. 各司其职&#x1f44b;&#xff08;1&#xff09;定义&#xff08;2&#xff09;例子阐述2. 组件封装&#x1f90f;&#xff08;1&#xff09;定义&#x…

leetcode104. 二叉树的最大深度(层序遍历09)

一:题目 二:上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*…

.NET Core 集成JWT认证

JWT(Json web token)就不用过多的介绍了&#xff0c;在 .NET Core 开发中使用JWT进行认证也是比较常见的&#xff0c;而且接入过程也比较简单&#xff0c;随便配置配置就好了。要想使用JWT&#xff0c;仅仅只需要在项目中引用微软的一个认证组件。Install-Package Microsoft.As…

leetcode111. 二叉树的最小深度(层序遍历10)

一:题目 二&#xff1a;上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(n…

拥抱.NET 5,可以从这个极速开发的Web应用框架开始

今年年初&#xff0c;微软 .NET 程序管理总监 Scott 在博客中表示&#xff0c;发布 .NET 5 的首个预览版&#xff0c;并提供SDK 和运行库下载。Scott 表示&#xff0c;.NET 5 是 .NET Framework 和 .NET Core 的未来&#xff0c;最终将成为一个统一平台&#xff0c;.NET5 将包含…

组件库实战 | 教你如何设计Web世界中的表单验证

教你如何设计Web世界中的表单验证&#x1f4ac;序言&#x1f5ef;️一、验证输入框ValidateInput1. 设计稿抢先知2. 简单的实现3. 抽象验证规则4. v-model5. 使用$attrs支持默认属性&#x1f4ad;二、验证表单ValidateForm1. 组件需求分析2. 使用插槽 slot3. 父子组件通讯&…

leetcode101. 对称二叉树(两种做法)

一&#xff1a;题目 二&#xff1a;上码 方法一&#xff1a;队列 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int …

微服务架构下的测试策略

源宝导读&#xff1a;最近几年&#xff0c;微服务架构越来越火爆&#xff0c;逐渐被企业所采用。随着软件架构的变化&#xff0c;对应的软件测试策略需要作何调整呢&#xff1f;本文将介绍云客在微服务架构下的测试策略。一、云客测试策略模型策略分析行业内的测试策略是一个先…

leetcode222. 完全二叉树的节点个数(两种做法)

一&#xff1a;题目 二&#xff1a;今天不上菜 上码了 方法一&#xff1a;前序遍历 求解 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr)…

听红宝书译者谈Web视角下的前端开发

Web视角下的前端开发⏳序言⏰一、关于前端开发1. 起源、架构、变迁&#xff08;1&#xff09;起源&#xff08;2&#xff09;架构&#xff08;3&#xff09;变迁2. 前端应用的领域&#xff08;1&#xff09;所面向群体&#xff08;2&#xff09;所面向领域3. 语言、框架、工具4…

在家办公这半年,让我开始热爱生活

距离上次更新公众号已经过去一年多了&#xff0c;感觉自己成了“年更姚”。不过好在这个公众号的读者大多是同事朋友&#xff08;加起来也没有多少好么喂&#xff09;&#xff0c;本身对我也没用太高的期待吧。今天想聊聊远程工作这件事。不过我并不想聊团队成员之间如何远程协…

每天都在红绿灯前面梭行,不如自己来实现个红绿灯?

用js实现一个交通灯&#x1f507;前言&#x1f508;一、需求分析 - 交通灯&#x1f509;二、实现版本1. 版本一&#xff1a;简单粗暴版2. 版本二&#xff1a;数据抽象版3. 版本三&#xff1a;过程抽象版4. 版本四&#xff1a;命令式和声明式&#x1f50a;三、在线online&#x…

Git 常用操作 | 重写 commit 历史

当我们修改完代码&#xff0c;提交了一个 commit&#xff0c;然后发现改错了&#xff0c;怎么修正&#xff1f;这种情况分为两种&#xff1a;修正最近一次提交&#xff0c;和修正历史多个提交。修正最近一次提交如果发现刚刚提交的内容有错误&#xff0c;当场再修改一下再提交一…

leetcode257. 二叉树的所有路径(两种做法)

一:题目 二:上码 1&#xff1a;DFS /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), …

【LeetCode之C#解法】 移动零、爬楼梯

题目官网链接https://leetcode-cn.com/problems/move-zeroes/283. 移动零给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。示例:输入: [0,1,0,3,12]输出: [1,3,12,0,0]说明:必须在原数组上操作&#xff0c;不能拷…

幂等问题 vs 如何判断是否是4的幂

判断是否是4的幂&#x1f939;序言&#x1f6b4;一、需求分析 - 判断是否是4的幂等&#x1f93e;二、实现版本1. 版本一&#xff1a;中规中矩法2. 版本二&#xff1a;按位与3. 版本三&#xff1a;按位与优化4. 版本四&#xff1a;正则匹配法⛹️三、结束语&#x1f93c;往期推荐…

leetcode404. 左叶子之和

一&#xff1a;题目 二:上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(n…

切西瓜法实现微信抢红包功能

运用切西瓜法和栅栏法实现微信抢红包功能✅前言☑️一、需求分析 - 分红包问题&#x1f199;二、实现版本1. 版本一&#xff1a;切西瓜法2. 版本二&#xff1a;栅栏法✳️三、在线Online&#x1f197;四、结束语&#x1f19a;往期推荐✅前言 在现实生活中&#xff0c;非常常见…

如何给扑克洗牌才能更公平?

如何给扑克牌洗牌才能更显公平性&#x1f4fb;前言一、&#x1f399;️需求分析 - 洗牌问题二、&#x1f4bf;实现版本1. 版本一&#xff1a;常规思维2. 版本二&#xff1a;验证公平性3. 版本三&#xff1a;交换法则三、&#x1f4fa;在线Online四、&#x1f4f9;结束语&#x…

这些年我是怎么自学成架构师的(转自知乎)

近日在知乎上一则关于程序员能否“自学成才”的问题&#xff0c;引发了激烈的讨论&#xff01;各种各样的说法都有&#xff0c;最终变成程序员晒学习经历的帖子。作为十多年.NET技术老兵&#xff0c;纯自学成架构师&#xff0c;也来分享下观点&#xff1a;自学当然有效&#xf…