快速创建 IEqualityComparer<T> 和 IComparer<T> 的实例
2012-03-19 09:49
549 查看
快速创建 IEqualityComparer<T> 和 IComparer<T> 的实例
2011-08-02 21:14 by 鹤冲天, 1935 visits,收藏,
编辑
几篇相关文章:《Linq的Distinct太不给力了》、《c# 扩展方法奇思妙用基础篇八:Distinct 扩展》、《何止
Linq 的 Distinct 不给力》,建议先看下。
.net 中 IEqualityComparer<T> 和 IComparer<T> 经常在 Linq 和 一些泛型集合、泛型字典类中用作参数。不过因其复杂性,包含 IEqualityComparer<T> 或 IComparer<T> 类型参数的函数一般使用频度不高。
尽管如此,有些情况下确非用不可,不得不创建一些新的类来实现 IEqualityComparer<T> 或 IComparer<T> 接口。不但增加了代码量,还对程序结构产生影响,新加入的类命名、放置、共用都是问题。
因此,我们期望能简单快速直接的创建 IEqualityComparer<T> 和 IComparer<T> 的实例。
本文给出两个实用类来实现这个目标,实现原理日后另撰文详述。
快速创建 IEqualityComparer<T> 的实例
我前一篇文章 《何止 Linq 的 Distinct 不给力》讨论的就是这个话题,这里就不再重复了,直接将 《何止 Distinct 不给力》一文中的总结出的实用类给出:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public static class Equality<T> { public static IEqualityComparer<T> CreateComparer<V>(Func<T, V> keySelector) { return new CommonEqualityComparer<V>(keySelector); } public static IEqualityComparer<T> CreateComparer<V>(Func<T, V> keySelector, IEqualityComparer<V> comparer) { return new CommonEqualityComparer<V>(keySelector, comparer); } class CommonEqualityComparer<V> : IEqualityComparer<T> { private Func<T, V> keySelector; private IEqualityComparer<V> comparer; public CommonEqualityComparer(Func<T, V> keySelector, IEqualityComparer<V> comparer) { this.keySelector = keySelector; this.comparer = comparer; } public CommonEqualityComparer(Func<T, V> keySelector) : this(keySelector, EqualityComparer<V>.Default) { } public bool Equals(T x, T y) { return comparer.Equals(keySelector(x), keySelector(y)); } public int GetHashCode(T obj) { return comparer.GetHashCode(keySelector(obj)); } } } |
使用示例:
1 2 3 4 | var equalityComparer1 = Equality<Person>.CreateComparer(p => p.ID); var equalityComparer2 = Equality<Person>.CreateComparer(p => p.Name); var equalityComparer3 = Equality<Person>.CreateComparer(p => p.Birthday.Year); var equalityComparer4 = Equality<Person>.CreateComparer(p => p.Name, StringComparer.CurrentCultureIgnoreCase); |
1 2 3 4 | class Person { public int ID { get; set; } public string Name { get; set; } public DateTime Birthday { get; set; } } |
快速创建 IComparer<T> 的实例
参照上面的代码,照猫画虎,很容易写出:1 2 3 4 | public static class Comparison<T> { public static IComparer<T> CreateComparer<V>(Func<T, V> keySelector) { return new CommonComparer<V>(keySelector); } public static IComparer<T> CreateComparer<V>(Func<T, V> keySelector, IComparer<V> comparer) { return new CommonComparer<V>(keySelector, comparer); } class CommonComparer<V> : IComparer<T> { private Func<T, V> keySelector; private IComparer<V> comparer; public CommonComparer(Func<T, V> keySelector, IComparer<V> comparer) { this.keySelector = keySelector; this.comparer = comparer; } public CommonComparer(Func<T, V> keySelector) : this(keySelector, Comparer<V>.Default) { } public int Compare(T x, T y) { return comparer.Compare(keySelector(x), keySelector(y)); } } } |
类似,Comparison<T> 的关键是 Comparer<V> 类和它的 Default 属性。
使用也是极其相似:
1 2 3 3 | var comparer1 = Comparison<Person>.CreateComparer(p => p.ID); var comparer2 = Comparison<Person>.CreateComparer(p => p.Name); var comparer3 = Comparison<Person>.CreateComparer(p => p.Birthday.Year); var comparer4 = Comparison<Person>.CreateComparer(p => p.Name, StringComparer.CurrentCultureIgnoreCase); |
总结
借助本文中的 Equality<T> 和 Comparison<T>,可以不必引入新的类、不必自己实现接口,也减少了编码和维护的工作量。预计 Equality<T> 和 Comparison<T> 类能满足多数需求。
如果本文对你有帮助,请推荐本文,让更多的朋友受益。
-------------------
思想火花,照亮世界
相关文章推荐
- 于快速创建 IEqualityComparer<T> 实例的类 Equality<T>
- 快速创建 IEqualityComparer<T> 和 IComparer<T> 的实例
- 快速创建 IEqualityComparer<T> 和 IComparer<T> 的实例
- IEqualityComparer<T> VS System.IEquatable<T>
- C#实现 Linq 序列的Distinct—— IEnumerable<T>.Distinct<T>()——IEqualityComparer
- 用泛型的IEqualityComparer<T>接口去重复项
- 快速创建 IEqualityComparer 实例:改进
- Distinct<TSource>(IEqualityComparer<TSource> comparer) 根据列名来Distinct
- Android实战简易教程<三十九>(第三方短信验证平台Mob和验证码自动填入功能结合实例)
- CommonEqualityComparer<T>
- 关于< tbody >的一个实例,很实用。
- 条件注释判断浏览器<!--[if !IE]><!--[if IE]><!--[if lt IE 6]><!--[if gte IE 6]>
- 条件注释判断IE浏览器,<!--[if IE]>条件注释区分非IE浏览器
- <实例>C++中交换两数值的几种方法
- Cocos2d-x中Vector<T>容器以及实例介绍
- IComparable<T> 与 IComparer<T>
- <MFC>创建对话框和新建对话框类
- MySQL索引的创建、删除和查看<转>
- 【转】<!--[if lte IE 6]>
- mysql insert一条记录(事务提交之前)怎样返回创建记录的主键id,last_insert_id(),selectkey && <select> 标签属性