在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. [转]将某个Qt4项目升级到Qt5遇到的问题

    原文:http://hi.baidu.com/xchinux/item/9044d8ce986accbb0d0a7b87晚上花了4个小时,将以前的一个项目从Qt 4.8.4-MinGW升级到了Qt5. ...

  2. android 69 SQLite数据库

    package com.itheima.sqlitedatabase; import java.sql.ResultSet; import android.content.Context; impor ...

  3. 安装MySQL和HandlerSocket

    CentOS 6.5MySQL 5.6.33HandlerSocket 1.1.2 # Get packagesshell> wget http://dev.mysql.com/get/Down ...

  4. 【转】正确使用Block避免Cycle Retain和Crash

    原文地址:http://tanqisen.github.io/blog/2013/04/19/gcd-block-cycle-retain/ 使用指南:http://blog.csdn.net/nic ...

  5. android开发之bitmap使用

    bitmap是android中重要的图像处理工具类,通过bitmap可以对图像进行剪切.旋转.缩放等操作,同时还可以指定格式和压缩质量保存图像文件. 一.拿到一个Bitmap对象 查看源码我们知道,B ...

  6. Android(java)学习笔记184:生成 4种 不同权限的文件

    1.首先我们编写一个生成 4种 不同权限的文件的程序案例: (1)首先是activity_main.xml文件: <RelativeLayout xmlns:android="http ...

  7. Linux系统性能测试工具sysbench

    1.CPU性能测试 sysbench --test=cpu --cpu-max-prime= --num-threads= run 2.内存性能测试 sysbench --test=memory -- ...

  8. ASP.NET获取汉字首字母

    /// <summary> /// 获取汉字首字母(可包含多个汉字) /// </summary> /// <param name="strText" ...

  9. 【原创教程】一、Angular教程系列之认识angular

    为什么我会准备写这个原创教程系列? 写下这个标题之后,看着屏幕上空白的内容区,不知从何下手,想说的似乎有很多,似乎又没啥说的.有时候就会陷入这种矛盾中,有时候就是这样,于是,我下定决心这一次一定要把这 ...

  10. 在自定义的web监听器中嵌入web中的定时事件

    在 http://www.cnblogs.com/myadmin/p/4806265.html 中说明了自定义web监听器的一些东西. 本文中的web定时任务也基于上篇文章的自定义web监听器. 新建 ...