在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅.

通过lambda表达式, 我们可以很方便地创建一个delegate:

下面两个语句是等价的

 Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/-->//using delegate syntax
Func<int, int> f = delegate(int i) { return ++i; }; //using lambda syntax
Func<int, int> f = i => ++i;

假如我要对一个列表进行排序:

 Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>
{
new Book
{
Id=,
Title="Design Patterns",
Authors= new List<string>{"Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"}
}, new Book
{
Id=,
Title="Refactoring",
Authors = new List<string>{"Martin Fowler"}
}
}; books.Sort((x, y) => x.Authors.Count - y.Authors.Count); //以作者个数进行排序
}
} public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public List<string> Authors { get; set; }
}
}

的确很方便吧!

我猜想List<T>应该提供了这样的方法:

 Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/-->1 //判断是否存在Id==1的书
bool has_book_with_id_equals_one = books.Contains(new Book { Id = }, (x, y) => x.Id == y.Id); //判断是否存在Title=="REFACTORING"(不区分大小写)的书
bool has_book_with_title_equals_refactoring_ignorecase = books.Contains(new Book { Title = "REFACTORING" }, x => x.Title.ToUpper());

不幸的是, List<T>没有这样的方法。

按照传统的方法, 你可能会这样写:

 Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/--> 1 //新增一个实现了IEqualityComparer<Book>接口的类
public class BookComparer : IEqualityComparer<Book>
{
public bool Equals(Book x, Book y)
{
return x.Id == y.Id;
}
public int GetHashCode(Book obj)
{
return obj.Id.GetHashCode();
}
}
//然后再干我们的活
bool has_book_with_id_equals_one = books.Contains(new Book { Id = }, new BookComparer());

很无奈的选择, 但是没办法!

幸运的是,我们可以自己动手扩展List<T>接口:

 Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/--> 1 public class KeyEqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> comparer;
private readonly Func<T, object> keyExtractor; // Allows us to simply specify the key to compare with: y => y.ID
public KeyEqualityComparer(Func<T, object> keyExtractor) : this(keyExtractor, null) { } // Allows us to tell if two objects are equal: (x, y) => y.Id == x.Id
public KeyEqualityComparer(Func<T, T, bool> comparer) : this(null, comparer) { } public KeyEqualityComparer(Func<T, object> keyExtractor, Func<T, T, bool> comparer)
{
this.keyExtractor = keyExtractor;
this.comparer = comparer;
} public bool Equals(T x, T y)
{
if (comparer != null)
return comparer(x, y);
else
{
var valX = keyExtractor(x);
if (valX is IEnumerable<object>) // The special case where we pass a list of keys
return ((IEnumerable<object>)valX).SequenceEqual((IEnumerable<object>)keyExtractor(y));
return valX.Equals(keyExtractor(y));
}
} public int GetHashCode(T obj)
{
if (keyExtractor == null)
return obj.ToString().ToLower().GetHashCode();
else
{
var val = keyExtractor(obj);
if (val is IEnumerable<object>) // The special case where we pass a list of keys
return (int)((IEnumerable<object>)val).Aggregate((x, y) => x.GetHashCode() ^ y.GetHashCode());
return val.GetHashCode();
}
}
} public static class MyExtMethod
{
public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, object> keyExtractor)
{
return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
} public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, T, bool> comparer)
{
return list.Contains(item, new KeyEqualityComparer<T>(comparer));
}
}

注意到上面的代码不仅仅针对Book,而是任意类型T

现在,我们就可以无拘无束地用我们的自己的扩展方法了(完整代码):

 Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>
{
new Book
{
Id=,
Title="Design Patterns",
Authors= new List<string>{"Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"}
}, new Book
{
Id=,
Title="Refactoring",
Authors = new List<string>{"Martin Fowler"}
}
}; books.Sort((x, y) => x.Authors.Count - y.Authors.Count); bool has_book_with_id_equals_one = books.Contains(new Book { Id = }, (x, y) => x.Id == y.Id); bool has_book_with_title_equals_refactoring_ignorecase = books.Contains(new Book { Title = "REFACTORING" }, x => x.Title.ToUpper()); }
} public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public List<string> Authors { get; set; }
} public class KeyEqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> comparer;
private readonly Func<T, object> keyExtractor; // Allows us to simply specify the key to compare with: y => y.Id
public KeyEqualityComparer(Func<T, object> keyExtractor) : this(keyExtractor, null) { } // Allows us to tell if two objects are equal: (x, y) => y.Id == x.Id
public KeyEqualityComparer(Func<T, T, bool> comparer) : this(null, comparer) { } public KeyEqualityComparer(Func<T, object> keyExtractor, Func<T, T, bool> comparer)
{
this.keyExtractor = keyExtractor;
this.comparer = comparer;
} public bool Equals(T x, T y)
{
if (comparer != null)
return comparer(x, y);
else
{
var valX = keyExtractor(x);
if (valX is IEnumerable<object>) // The special case where we pass a list of keys
return ((IEnumerable<object>)valX).SequenceEqual((IEnumerable<object>)keyExtractor(y));
return valX.Equals(keyExtractor(y));
}
} public int GetHashCode(T obj)
{
if (keyExtractor == null)
return obj.ToString().ToLower().GetHashCode();
else
{
var val = keyExtractor(obj);
if (val is IEnumerable<object>) // The special case where we pass a list of keys
return (int)((IEnumerable<object>)val).Aggregate((x, y) => x.GetHashCode() ^ y.GetHashCode());
return val.GetHashCode();
}
}
} /// <summary>
/// 扩展方法
/// </summary>
public static class MyExtMethod
{
public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, object> keyExtractor)
{
return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
} public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, T, bool> comparer)
{
return list.Contains(item, new KeyEqualityComparer<T>(comparer));
}
}
}

Lambda表达式, 可以让我们的代码更优雅.的更多相关文章

  1. Java 8 Lambda表达式,让你的代码更简洁

    Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift等都已经支持La ...

  2. JDK8漫谈——代码更优雅

    简介 lambda表达式,又称闭包(Closure)或称匿名方法(anonymous method).将Lambda表达式引入JAVA中的动机源于一个叫"行为参数"的模式.这种模式 ...

  3. JAVA8-让代码更优雅之List排序

    先定义一个实体类 @Data @AllArgsConstructor @NoArgsConstructor public class Human { private String name; priv ...

  4. CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅

    首页   登录注册         CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅 阅读 8113 收藏 927 2017-09-26 原文链接:github.com 腾讯云容器服务CSS,立 ...

  5. 用Assert(断言)封装异常,让代码更优雅(附项目源码)

    有关Assert断言大家并不陌生,我们在做单元测试的时候,看业务事务复合预期,我们可以通过断言来校验,断言常用的方法如下: public class Assert { /** * 结果 = 预期 则正 ...

  6. 使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测

    概述 单测是提升软件质量的有力手段.然而,由于编程语言上的支持不力,以及一些不好的编程习惯,导致编写单测很困难. 最容易理解最容易编写的单测,莫过于独立函数的单测.所谓独立函数,就是只依赖于传入的参数 ...

  7. 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework 之让代码更优雅

    [前言] 大家好,我是TANZAME.出乎意料的,我们在立冬的前一天又见面了,天气慢慢转凉,朋友们注意添衣保暖,愉快撸码.距离 TZM.XFramework 的首秀已数月有余,期间收到不少朋友的鼓励. ...

  8. source 1.7 中不支持 lambda 表达式(请使用 -source 8 或更高版本以启用 lambda 表达式)

    from:http://blog.csdn.net/qwdafedv/article/details/54691740 https://www.youtube.com/watch?v=oXxijdf8 ...

  9. 使用Object#tap使代码更优雅

    今天看spree源码的时候经常看到Object#tap方法.以前只知道有这个方法,而且感觉这个方法调试的作用大于实际,今日看来以前的理解应该不够准确. 先看下官方文档上tap的例子 Yields se ...

随机推荐

  1. NIO组件Selector调用实例

    *对于nio的非阻塞I/O操作,使用Selector获取哪些I/O准备就绪,注册的SelectionKey集合记录关联的Channel这些信息.SelectionKey记录Channel对buffer ...

  2. 在地图上添加POI

    使用Tangram的Marker, 可以在地图上做各种标记, 效果图: Tangram是通过Marker在地图上添加标记的,Marker分Point, Polyline和Polygon三种, 分别对应 ...

  3. 在mysql中修改表名的sql语句

    在使用mysql时,经常遇到表名不符合规范或标准,但是表里已经有大量的数据了,如何保留数据,只更改表名呢?可以通过建一个相同的表结构的表,把原来的数据导入到新表中,但是这样视乎很麻烦.能否简单使用一个 ...

  4. python如何使用 os.path.exists()--Learning from stackoverflow 分类: python 2015-04-23 20:48 139人阅读 评论(0) 收藏

    Q&A参考连接 Problem:IOError: [Errno 2] No such file or directory. os.path.exists() 如果目录不存在,会返回一个0值. ...

  5. oracle6

    转换函数  介绍 转换函数用于将数据类型从一种转为另外一种.在某些情况下,oracle server允许值的数据类型和实际的不一样,这时oracle server会隐含的转化数据类型 比如: crea ...

  6. jsp-javabean-setproperty介绍

    李兴华<java web开发实战经典>第7章关于javabean的讲解中说道:<jsp:setProperty>标签一共有4种使用方法·下面列出了4种操作语法的格式:   设置 ...

  7. springmvc 返回xml

    需求: 1.springmvc返回xml: 技术及环境: Spring 4.3.1.RELEASE JDK 1.8 IDEA 15.0.6 Maven 3 实现: spirngxml的配置主要如下: ...

  8. 菱形实现气泡Bubble,菱形画箭头,菱形画三角形

    菱形实现气泡Bubble,菱形画箭头,菱形画三角形 >>>>>>>>>>>>>>>>>>&g ...

  9. java: Eclipse jsp tomcat 环境搭建(完整)

    ] 欢迎您! 要学习一门语言,首先要做的就是搭建环境,然后能写一个小的Demo(类似Helloworld),不仅可以建立信心,而且还可以为之后的学习搭建一个验证平台,事半功倍. net领域的vs,号称 ...

  10. Android- Context理解

    学习了安卓以后还是不理解Context的用法:Api文档链接http://wear.techbrood.com/reference/android/content/Context.html 一个非常好 ...