• 小谈IEqualityComparer<T>接口


         今天,想使用自定义的类型作为Dictionary<TKey, TValue> 的键类型,不可避免的要使用到这个接口。如果另外定义一个实现类,使用者必须首先知道有这个类存在,这样调用方才会得到正确的结果。自然想到的办法就是这个自定义类型主动实现IEqualityComparer<T>接口,但是Dictionary<TKey, TValue> 类型并不会去检查这个键对象有没有实现IEqualityComparer<T>接口。

         如果构造Dictionary<TKey, TValue> 泛型集合的实例对象时候,没有提供一个实现了IEqualityComparer<T>接口的实例对象,Dictionary<TKey, TValue>默认使用EqualityComparer<T> 泛型类的 Default属性。看看IEqualityComparer<T>接口MSDN的说明:使用此接口,可以实现集合的自定义相等比较。也就是说,对于类型 T,您可以创建自己的相等定义,并指定该定义可与接受 IEqualityComparer<T>泛型接口的集合类型一起使用。在 .NET Framework 中,Dictionary<TKey, TValue> 泛型集合类型的构造函数接受此接口。继续看EqualityComparer<T> 泛型类Default属性的MSDN的说明:Default 属性检查类型 T 是否实现此 System.IEquatable<T> 泛型接口,如果实现,该属性将返回一个使用该实现的 EqualityComparer<T>。否则,它返回一个使用 T 提供的 Object.Equals 和 Object.GetHashCode 的重写的 EqualityComparer<T>。

         看到上面的说明,我天真的以为实现了System.IEquatable<T> 泛型接口就可以在Dictionary<TKey, TValue> 泛型集合的键中使用自己定义的类了。结果发现无论如何都不能使程序按照设想中的运行。最后发现MSDN中关于System.IEquatable<T>的实现者说明:如果实现 IEquatable<T>,还应重写 Object.Equals(Object) 和 GetHashCode 的基类实现,以便其行为与 IEquatable<T>.Equals 方法的行为一致。尝试着重写了这两个方法,一切都OK了。后来查看了.Net Framework源代码才明白了,实际上,对于EqualityComparer<T> 泛型类来说前面这个重写是必须的,因为前面说的“Default 属性检查类型 T 是否实现此 System.IEquatable<T> 泛型接口,如果实现,该属性将返回一个使用该实现的 EqualityComparer<T>”,实际上这个未公开的 System.IEquatable<T>实现内部其实使用的还是Object.Equals(Object)方法来做比较。

         这就比较郁闷了,对于Dictionary<TKey, TValue>来说,实现System.IEquatable<T>其实没什么用,始终还是要重写 Object.Equals(Object) 和 GetHashCode。

         有关的文章可以看这两篇:

         1、http://www.joycode.com/vbcti/archive/2009/02/20/115473.joy

         2、http://www.cnblogs.com/ldp615/archive/2009/09/05/1560791.html

  • 相关阅读:
    狗 日 的 360
    Django搭建简单的站点
    ZOJ 3675 Trim the Nails(bfs)
    Qt移动应用开发(二):使用动画框架
    SPOJ QTREE2 lct
    [Phonegap+Sencha Touch] 移动开发77 Cordova Hot Code Push插件实现自己主动更新App的Web内容
    Bitmap工具类BitmapHelper
    Material-design icon生成插件
    闲聊ROOT权限——ROOT权限的前世今生
    Java深入浅出系列(四)——深入剖析动态代理--从静态代理到动态代理的演化
  • 原文地址:https://www.cnblogs.com/wenhx/p/Dictionary_IEqualityComparer.html
Copyright © 2020-2023  润新知