amplt,快速创建 IEqualityComparer<T> 和 IComparer<T> 的实例

几篇相关文章:《Linq的Distinct太不给力了》、《c# 扩展方法奇思妙用基础篇八:Distinct 扩展》、《何止 Linq 的 Distinct 不给力》,建议先看下。
.net 中 IEqualityComparer 和 IComparer 经常在 Linq 和 一些泛型集合、泛型字典类中用作参数。不过因其复杂性,包含 IEqualityComparer 或 IComparer 类型参数的函数一般使用频度不高。 尽管如此,有些情况下确非用不可,不得不创建一些新的类来实现 IEqualityComparer 或 IComparer 接口。不但增加了代码量,还对程序结构产生影响,新加入的类命名、放置、共用都是问题。 因此,我们期望能简单快速直接的创建 IEqualityComparer 和 IComparer 的实例。
本文给出两个实用类来实现这个目标,实现原理日后另撰文详述。

快速创建 IEqualityComparer 的实例

我前一篇文章 《何止 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 { public static IEqualityComparer CreateComparer(Func keySelector) { return new CommonEqualityComparer(keySelector); } public static IEqualityComparer CreateComparer(Func keySelector, IEqualityComparer comparer) { return new CommonEqualityComparer(keySelector, comparer); } class CommonEqualityComparer : IEqualityComparer { private Func keySelector; private IEqualityComparer comparer; public CommonEqualityComparer(Func keySelector, IEqualityComparer comparer) { this.keySelector = keySelector; this.comparer = comparer; } public CommonEqualityComparer(Func keySelector) : this(keySelector, EqualityComparer.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)); } } }
Equality 代码比较简洁,其中的关键是 EqualityComparer 类和它的 Default 属性(有时间专门写篇文章来讲解)。
使用示例:
1 2 3
var equalityComparer1 = Equality.CreateComparer(p => p.ID); var equalityComparer2 = Equality.CreateComparer(p => p.Name); var equalityComparer3 = Equality.CreateComparer(p => p.Birthday.Year);
Person 是一个简单的实体类:
1 2 3 4 5 6
class Person { public int ID { get; set; } public string Name { get; set; } public DateTime Birthday { get; set; } }

快速创建 IComparer 的实例

参照上面的代码,照猫画虎,很容易写出:
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
public static class Comparison { public static IComparer CreateComparer(Func keySelector) { return new CommonComparer(keySelector); } public static IComparer CreateComparer(Func keySelector, IComparer comparer) { return new CommonComparer(keySelector, comparer); } class CommonComparer : IComparer { private Func keySelector; private IComparer comparer; public CommonComparer(Func keySelector, IComparer comparer) { this.keySelector = keySelector; this.comparer = comparer; } public CommonComparer(Func keySelector) : this(keySelector, Comparer.Default) { } public int Compare(T x, T y) { return comparer.Compare(keySelector(x), keySelector(y)); } } }
类似,Comparison 的关键是 Comparer 类和它的 Default 属性。
使用也是极其相似:
1 2 3
var comparer1 = Comparison.CreateComparer(p => p.ID); var comparer2 = Comparison.CreateComparer(p => p.Name); var comparer3 = Comparison.CreateComparer(p => p.Birthday.Year);

总结

借助本文中的 Equality 和 Comparison,可以不必引入新的类、不必自己实现接口,也减少了编码和维护的工作量。 预计 Equality 和 Comparison 类能满足多数需求。 如果本文对你有帮助,请推荐本文,让更多的朋友受益。
Tags:  ltbrgt ltgt ampgt amplt

延伸阅读

最新评论

发表评论