如何正确看待Linq的DistinctBy扩展和ForEach扩展
在微软标准的Linq中,并没有DistinctBy扩展和ForEach扩展,但在平时使用工作中却又经常需要使用到这两个功能,照理来说,微软在Linq中应该包含这两个扩展才对,可事实上为什么并没有呢?本文我就来说说自己对这两个扩展的理解!
关于DistinctBy扩展
顾名思义,DistinctBy扩展就是根据一个键值进行唯一性的筛选,将有重复键值的元素剔除,仅保留一个!当然Linq中有Distinct扩展,但其功能简直是弱爆了!用过的同志相信都对Distinct扩展吐槽无数遍了吧!如果你要使用Distinct扩展实现DistinctBy扩展的功能,还要专门定义一个辅助类!Oh,My God!这简直是对程序员的谋杀!但是等经历过无数个纠结之后,我突然发现,微软在标准的Linq中实际上是包含了DistinctBy扩展的功能的,只不过不那么直接,看下面的示例代码:
class Person
{
public int Age { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("Age:{0} Name:{1}", Age, Name);
}
}
[STAThread]
static void Main()
{
var persons = new[] {
new Person{Age = ,Name="a"},
new Person{Age = ,Name="b"},
new Person{Age = ,Name="c"},
new Person{Age = ,Name="d"}
};
foreach (var p in persons.GroupBy(o=>o.Age).Select(g=>g.First()))
{
Console.WriteLine(p);
}
}
运行结果

从结果看,代码成功完成了根据键值Age进行Distinct的操作。
明眼人可能一眼就看出来了,不错,就是使用GroupBy、Select和First这三个子操作组合出DistinctBy的功能!只不过实现一个DistinctBy功能需要写这么做代码实在是不好,于是可以封装一下,把GroupBy、Select和First这三个子操作的组合封装成一个DistinctBy扩展方法,就可以方便的使用了。封装的代码 too simple,就不贴上来了!
关于ForEach扩展
为什么微软不在Linq中添加ForEach扩展,这个问题的讨论在网上已经很多了,总结一下主要是有下面几点原因:
1.Linq中已经有Select扩展了,因此不必在实现一个ForEach,因为在大多数情况下可以用Select来实现ForEach的功能(当然我不建议这样做,因为Select是延迟操作,如果仅仅实现ForEach功能,有些时候代码不能够按照设计意图正确运行);
2.ForEach破坏了Linq的编程模式,就是说破坏了链式编程模式,所谓链式编程,大概的意思就是将多个操作通过点号"."链接在一起,相信写过Linq的同志很清楚这句话的含义吧!
我看到网上有人这么来设计ForEach扩展:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> foreachAction)
{
foreach (var t in source)
{
foreachAction(t);
}
}
我不得不说这是简直是对Linq的“亵渎”啊,试想,如果别人使用了你的这个ForEach之后,后续操作岂不是成天方夜谭了吗?所以说这样设计ForEach是万万不可的!即使勉强要设计,也要设计成这样才对啊!
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> foreachAction)
{
foreach (var t in source)
{
foreachAction(t);
}
return source;
}
而且在我看来,这样添加ForEach扩展并不妥当,原因在于:这样设计的ForEach扩展,破坏了Linq的延迟操作特性!
所以说,我认为微软不在Linq中包含ForEach扩展算是一个正确的选择,如果要用到ForEach功能,还是老老实实用foreach语句来写吧!其实也并不复杂!
如何正确看待Linq的DistinctBy扩展和ForEach扩展的更多相关文章
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- 正确看待POW与POS,总结与区分
POW:Proof of Work,工作证明. 比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值.要得到合理的Block ...
- 学习Linq之前必须要了解的扩展方法
本文主要以下面几个方面来详细讲解扩展方法:在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候).扩展方法的语法及怎么使用.怎么正确的使用扩展方法: 一.首先说一下在C#3.0之前没 ...
- 理解水平扩展和垂直扩展 (转载 http://yunjiechao-163-com.iteye.com/blog/2126981)
当一个开发人员提升计算机系统负荷时,通常会考虑两种方式垂直扩展和水平扩展.选用哪种策略主要依赖于要解决的问题 以及系统资源的限制.在这篇文章中我们将讲述这两种策略并讨论每种策越的优缺点.如果你已经 ...
- Web 站点的水平扩展和垂直扩展 (译文)
当一个开发人员提升计算机系统负荷时,通常会考虑两种方式垂直扩展和水平扩展.选 用哪种策略主要依赖于要解决的问题以及系统资源的限制.在这篇文章中我们将讲述这两种策略并讨论每种策越的优缺点.如果你已经有一 ...
- 使用扩展方法(this 扩展类型)
namespace ConsoleApp_UseExtendWays{ class Program { static void Main(string[] args) { Student s = ne ...
- 在 Windows Azure 网站中进行纵向扩展和横向扩展
编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Byron Tardif 撰写. 当您开始一个新的 Web 项目,或者刚刚开始开发一般的网站和应用程序时,您可能希望从小处着手. ...
- Linq常用List操作总结,ForEach、分页、交并集、去重、SelectMany等
/* 以下围绕Person类实现,Person类只有Name和Age两个属性 一.List<T>排序 1.1 List<T>提供了很多排序方法,sort(),Orderby() ...
- AutoCAD中的扩展字典及扩展记录(C#)
在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得.在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode.感兴趣的也可以了解一下扩展数据的相关内 ...
随机推荐
- hdu 4374 单调队列优化动态规划
思路:我只想说,while(head<=rear&&que[rear].val+sum[j]-sum[que[rear].pos-1]<=dp[i-1][j]+num[i- ...
- <转>HTML+CSS总结/深入理解CSS盒子模型
原文地址:http://www.chinaz.com/design/2010/1229/151993.shtml 前言:前阵子在做一个项目时,在页面布局方面遇到了一点小问题,于是上stackoverf ...
- Spring(3.2.3) - Beans(2): 属性注入 & 构造注入
依赖注入是指程序运行过程中们如果需要另外的对象协作(访问它的属性或调用它的方法)时,无须在代码中创建被调用者,而是依赖于外部容器的注入. 属性注入(Setter Injection) 属性注入是指 I ...
- JS定位PDF页码。
由于项目中的PDF文章段落标题有些是英文,对其翻译后需要定位到具体的页码. 查询相关资料及进行尝试后发现可以用如下方法可以实现 function gotoPage(page) { ...
- HDOJ2000ASCII码排序
ASCII码排序 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- 图片上传即时显示javascript代码
这是基于javascript的一种图片上传即时显示方法,测试结果IE6和火狐浏览器可以正常使用.google浏览器不兼容. 这种方法兼容性比较差,仅供参考,建议使用ajax方法来即时显示图片. 1.首 ...
- 我眼中的go的语法特点
因为基本从c#/javascript/c/c++/python/lua/action script,一路走来,对所有的C系列的语法既熟悉又有好感: 那在看语言的时候肯定会与C系列的东西进行类比,那就总 ...
- 给label text 上色 && 给textfiled placeholder 上色
1.给label text 上色: NSInteger stringLength = ; stringLength = model.ToUserNickName.length; NSMutableAt ...
- 值类型与引用类型(特殊的string) Typeof和GetType() 静态和非静态使用 参数传递 相关知识
学习大神博客链接: http://www.cnblogs.com/zhili/category/421637.html 一 值类型与引用类型 需要注意的string 是特殊类型的引用类型. 使用方法: ...
- String.Trim
String.Trim有2个重载方法,分别是:Trim()和Trim(char[]),根据官方的解释 Trim():从当前String对象移除所有前导空白字符和尾部空白字符. Trim(char[]) ...