Lambda表达式, 可以让我们的代码更优雅.
2010-05-27 13:50
856 查看
在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅.
通过lambda表达式, 我们可以很方便地创建一个delegate:
下面两个语句是等价的
但我更喜欢后者!
假如我要对一个列表进行排序:
的确很方便吧!
我猜想List<T>应该提供了这样的方法:
不幸的是, List<T>没有这样的方法。
按照传统的方法, 你可能会这样写:
很无奈的选择, 但是没办法!
幸运的是,我们可以自己动手扩展List<T>接口:
注意到上面的代码不仅仅针对Book,而是任意类型T
现在,我们就可以无拘无束地用我们的自己的扩展方法了(完整代码):
通过lambda表达式, 我们可以很方便地创建一个delegate:
下面两个语句是等价的
//using delegate syntax Func<int, int> f = delegate(int i) { return ++i; }; //using lambda syntax Func<int, int> f = i => ++i;
但我更喜欢后者!
假如我要对一个列表进行排序:
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=1, Title="Design Patterns", Authors= new List<string>{"Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"} }, new Book { Id=2, 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>应该提供了这样的方法:
//判断是否存在Id==1的书 bool has_book_with_id_equals_one = books.Contains(new Book { Id = 1 }, (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>没有这样的方法。
按照传统的方法, 你可能会这样写:
//新增一个实现了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 = 1 }, new BookComparer());
很无奈的选择, 但是没办法!
幸运的是,我们可以自己动手扩展List<T>接口:
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
现在,我们就可以无拘无束地用我们的自己的扩展方法了(完整代码):
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=1, Title="Design Patterns", Authors= new List<string>{"Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"} }, new Book { Id=2, 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 = 1 }, (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)); } } }
相关文章推荐
- 前端神器推荐—我们也可以高效优雅的写代码
- java中提供了对正则表达式的支持。 有的时候,恰当地使用正则,可以让我们的工作事半功倍! 如下代码用来检验一个四则运算式中数据项的数目,请填写划线部分缺少的代码。 注意:只填写缺少代码,不要
- for_each + lambda 优雅的写代码
- 注意:我们不能在模式匹配中放入lambda 表达式
- 可以节约很多代码的几个正则表达式
- 你的代码可以是优雅的,但是还有更重要的
- java8新特性lambda表达式, 函数式接口以及Steam流和新的日期时间例子代码
- dedecms采集中可以过滤多行代码的正则表达式
- c#隐藏函数 lambda表达式 泛型综合使用代码
- C# 从CIL代码了解委托,匿名方法,Lambda 表达式和闭包本质
- window的画图工具(mspaint)也可以帮助我们开发和调试代码的.
- 表达式即编译器(也许.Net代码还可以这么写)
- 这是一个求两数之和的题目,输入多对用空格分开的两个数a b,输出a+b的和,每一对数据的和占一行。编写代码时需要注意的是,由于没有指出有多少对输入数据,因此我们可以编写如下代码:
- 可视化编程 Tips 之"无需代码设置圆角" "简单处理让我们可以无需代码设置边框颜色"
- Java8 Lambda表达式和流操作如何让你的代码变慢5倍
- 代码之美~Lambda带给我们的不只是简洁
- android studio 使用retrolambda库 让代码支持lambda 表达式
- Java 8 之 lambda 表达式简单使用入门实例代码。
- 软件开发者面试百问-----怎么样让我们的代码可以处理各种错误事件?
- 超轻量级异步JS框架,别再让嵌套影响我们的优雅代码!