在微软标准的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扩展的更多相关文章

  1. Linq分组操作之GroupBy,GroupJoin扩展方法源码分析

    Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...

  2. 正确看待POW与POS,总结与区分

    POW:Proof of Work,工作证明. 比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值.要得到合理的Block ...

  3. 学习Linq之前必须要了解的扩展方法

    本文主要以下面几个方面来详细讲解扩展方法:在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候).扩展方法的语法及怎么使用.怎么正确的使用扩展方法: 一.首先说一下在C#3.0之前没 ...

  4. 理解水平扩展和垂直扩展 (转载 http://yunjiechao-163-com.iteye.com/blog/2126981)

      当一个开发人员提升计算机系统负荷时,通常会考虑两种方式垂直扩展和水平扩展.选用哪种策略主要依赖于要解决的问题 以及系统资源的限制.在这篇文章中我们将讲述这两种策略并讨论每种策越的优缺点.如果你已经 ...

  5. Web 站点的水平扩展和垂直扩展 (译文)

    当一个开发人员提升计算机系统负荷时,通常会考虑两种方式垂直扩展和水平扩展.选 用哪种策略主要依赖于要解决的问题以及系统资源的限制.在这篇文章中我们将讲述这两种策略并讨论每种策越的优缺点.如果你已经有一 ...

  6. 使用扩展方法(this 扩展类型)

    namespace ConsoleApp_UseExtendWays{ class Program { static void Main(string[] args) { Student s = ne ...

  7. 在 Windows Azure 网站中进行纵向扩展和横向扩展

    编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Byron Tardif 撰写. 当您开始一个新的 Web 项目,或者刚刚开始开发一般的网站和应用程序时,您可能希望从小处着手. ...

  8. Linq常用List操作总结,ForEach、分页、交并集、去重、SelectMany等

    /* 以下围绕Person类实现,Person类只有Name和Age两个属性 一.List<T>排序 1.1 List<T>提供了很多排序方法,sort(),Orderby() ...

  9. AutoCAD中的扩展字典及扩展记录(C#)

    在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得.在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode.感兴趣的也可以了解一下扩展数据的相关内 ...

随机推荐

  1. Java Concurrency - Concurrent Collections

    Data structures are a basic element in programming. Almost every program uses one or more types of d ...

  2. Android的按钮单击事件及监听器四种常见的实现方式

    第一种:匿名内部类作为事件监听器类<ignore_js_op>大部分时候,事件处理器都没有什么利用价值(可利用代码通常都被抽象成了业务逻辑方法),因此大部分事件监听器只是临时使用一次,所以 ...

  3. python学习day1--python基础

    Python的优缺点 先看优点 Python的定位是“优雅”.“明确”.“简单”,所以Python程序看上去总是简单易懂,初学者学Python,不但入门容易,而且将来深入下去,可以编写那些非常非常复杂 ...

  4. Windows命令实现Sleep

    等待一分钟:ping 192.0.2.2 -n 1 -w 60000 > nul 等待一秒钟:ping 192.0.2.2 -n 1 > nul (ping一次需要一秒钟) -w 6000 ...

  5. [Bootstrap]全局样式(四)

    按钮 1.基本类.btn {display/padding/margin-bottom/font-size/border-radius/border} 作用于< a:role:button &g ...

  6. EL表达式获取Map和List中的值

    EL表达式获取Map和List中的值   EL表达式取Map中的值: 当Map中是String,String时 后台servlet中: Map<String, String> map1 = ...

  7. Science论文"Clustering by fast search and find of density peaks"学习笔记

    "Clustering by fast search and find of density peaks"是今年6月份在<Science>期刊上发表的的一篇论文,论文中 ...

  8. log4j配置只打印指定jar或包的DEBUG信息

    有的时候查问题的时候需要打印第三方jar里面的debug信息,假如全部jar都打印的话日志文件会很大,这个时候可以配置log4j只打印指定jar的debug信息或者包,同时输出到了一个新的文件中. 比 ...

  9. c#中的枚举

    1.枚举概念:枚举是用户定义的整型类型,在声明一个枚举时,要指定该枚举的实例可以包含的一组可接受的值,还可以给值指定易于记忆的名称.如果在代码的某个地方,要试图把一个不可接受范围内的值赋予枚举的一个实 ...

  10. YII千万级PV架构经验分享--理论篇

    hello,大家好,我是方少,现在想象一下这样一个情景,这是一个很惬意的季节,是一个可以随意乱穿的季节,两个人,一个穿羽绒服,一个穿热裤,小胡同里两人迎面走来,看到对方都哈哈大笑,前仰后合,笑完都甩一 ...