Lambda表达式, 可以让我们的代码更优雅.
在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表达式, 可以让我们的代码更优雅.的更多相关文章
- Java 8 Lambda表达式,让你的代码更简洁
Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift等都已经支持La ...
- JDK8漫谈——代码更优雅
简介 lambda表达式,又称闭包(Closure)或称匿名方法(anonymous method).将Lambda表达式引入JAVA中的动机源于一个叫"行为参数"的模式.这种模式 ...
- JAVA8-让代码更优雅之List排序
先定义一个实体类 @Data @AllArgsConstructor @NoArgsConstructor public class Human { private String name; priv ...
- CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅
首页 登录注册 CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅 阅读 8113 收藏 927 2017-09-26 原文链接:github.com 腾讯云容器服务CSS,立 ...
- 用Assert(断言)封装异常,让代码更优雅(附项目源码)
有关Assert断言大家并不陌生,我们在做单元测试的时候,看业务事务复合预期,我们可以通过断言来校验,断言常用的方法如下: public class Assert { /** * 结果 = 预期 则正 ...
- 使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测
概述 单测是提升软件质量的有力手段.然而,由于编程语言上的支持不力,以及一些不好的编程习惯,导致编写单测很困难. 最容易理解最容易编写的单测,莫过于独立函数的单测.所谓独立函数,就是只依赖于传入的参数 ...
- 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework 之让代码更优雅
[前言] 大家好,我是TANZAME.出乎意料的,我们在立冬的前一天又见面了,天气慢慢转凉,朋友们注意添衣保暖,愉快撸码.距离 TZM.XFramework 的首秀已数月有余,期间收到不少朋友的鼓励. ...
- source 1.7 中不支持 lambda 表达式(请使用 -source 8 或更高版本以启用 lambda 表达式)
from:http://blog.csdn.net/qwdafedv/article/details/54691740 https://www.youtube.com/watch?v=oXxijdf8 ...
- 使用Object#tap使代码更优雅
今天看spree源码的时候经常看到Object#tap方法.以前只知道有这个方法,而且感觉这个方法调试的作用大于实际,今日看来以前的理解应该不够准确. 先看下官方文档上tap的例子 Yields se ...
随机推荐
- 设计 REST 风格的 MVC 框架
http://www.ibm.com/developerworks/cn/java/j-lo-restmvc/ 传统的 JavaEE MVC 框架如 Struts 等都是基于 Action 设计的后缀 ...
- Android自定义“图片+文字”控件四种实现方法之 二--------个人最推荐的一种
http://blog.csdn.net/yanzi1225627/article/details/8633872 第二种方法也要新建一个图片+文字的xml布局文件,然后写一个类继承自LinearLa ...
- jQuery--对话框插件--dialog
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Hadoop-2.4.1学习之Map任务源代码分析(下)
在Map任务源码分析(上)中,对MAP阶段的代码进行了学习,这篇文章文章将学习Map任务的SORT阶段.假设Reducer的数量不为0.则还须要进行SORT阶段.但从上面的学习中并未发现与MAP阶段运 ...
- Mysql : L闪存卡linux中的内核参数设置
将 Nytro WarpDrive 加速卡配置为文件系统 本节说明的操作使您可调整 Nytro WarpDrive 加速卡,增强使用 Oracle Linux with Unbreakable Ent ...
- iOS AFNetWorking源码详解(一)
来源:Yuzeyang 链接:http://zeeyang.com/2016/02/21/AFNetWorking-one/ 首先来介绍下AFNetWorking,官方介绍如下: AFNetworki ...
- hdu2025java字符题
查找最大元素 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- CentOS Linux修改系统时区
ln –sf /usr/share/zoneinfo/Hongkong /etc/localtime
- 利用mysql中的SQL_CALC_FOUND_ROWS 来实现group by后的记录数统计
最近正在做一个显示消息的列表页,列表页中需要根据一个字段来分组显示.并且需要一个分页的效果. 大家也知道group by 后的数据是每一组一行记录,统计分组后的总的记录数又不能用count,所以SQL ...
- Bootstrap--全局css样式之表单
单独的表单控件会被自动赋予一些全局样式.所有设置了 .form-control 类的 <input>.<textarea> 和 <select> 元素都将被默认设置 ...