http://blog.csdn.net/wyfde123/archive/2011/05/05/6397130.aspx#

关于C#的hashcode一直有些疑问:

1、为什么重写了Equals方法还要同时重写GetHashCode方法?

2、哈希码用在Hashtable和Dictionary中用于索引项,但是哈希码是一样的情况下怎么办呢?

3、GetHashCode方法为什么要放在Object里面?

解答
带着这些疑问,查阅了一下MSDN,摘抄了几段

哈希代码是一个用于在相等测试过程中标识对象的数值。 它还可以作为一个集合中的对象的索引。

.NET Framework 不保证 GetHashCode 方法的默认实现以及它所返回的值在不同版本的 .NET Framework 中是相同的。 因此,在进行哈希运算时,该方法的默认实现不得用作唯一对象标识符。

哈希函数必须具有以下特点:

如果两个对象的 Equals 比较结果相等,则每个对象的 GetHashCode 方法都必须返回同一个值。 但是,如果两个对象的比较结果不相等,则这两个对象的 GetHashCode 方法不一定返回不同的值。

一个对象的 GetHashCode 方法必须总是返回同一个哈希代码,但前提是没有修改过对象状态,对象状态用来确定对象的 Equals 方法的返回值。请注意,这仅适用于应用程序的当前执行,再次运行该应用程序时可能会返回另一个哈希代码。

为了获得最佳性能,哈希函数必须为所有输入生成随机分布。

从特点一能够得出第一个问题的答案,Object中的Equals方法只是简单判断两个对象是不是引用同一个对象,而由于Object中没有任何实例字段GetHashCode方法返回的哈希码能作为全局唯一的标识,但是值类型基类的GetHashCode方法则使用了反射,效率也比较低。

下面来解答第二个问题

首先定义一个重写了GetHashCode方法的类,这里为了测试把两个int相加作为哈希码

view plaincopy to clipboardprint?
class Class3  
   {  
       public int x;  
       int y;  
       public Class3(int x, int y)  
       {  
           this.x = x;  
           this.y = y;  
       }  
       public override int GetHashCode()  
       {  
           Console.WriteLine("判断hashcode");  
           return x + y;  
       }  
       public override bool Equals(object obj)  
       {  
           Console.WriteLine("判断equals");  
           return base.Equals(obj);  
       }  
       public override string ToString()  
       {  
           return x.ToString() + y.ToString();  
       }  
   } 
class Class3
    {
        public int x;
        int y;
        public Class3(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public override int GetHashCode()
        {
            Console.WriteLine("判断hashcode");
            return x + y;
        }
        public override bool Equals(object obj)
        {
            Console.WriteLine("判断equals");
            return base.Equals(obj);
        }
        public override string ToString()
        {
            return x.ToString() + y.ToString();
        }
    }

接着在控制台程序里测试下,

在插入了cc之后把cc的状态更改了,再通过哈希表中cc那项的key访问值则什么也不会输出,因为在哈希表中找不到cc的哈希码对应的项

正确的做法是把cc那项remove掉再重新插入新的cc项。

view plaincopy to clipboardprint?
Hashtable ht = new Hashtable();  
Class3 cc = new Class3(2, 3);  
Class3 cc2 = new Class3(1, 4);  
Class3 cc3 = new Class3(3, 3);  
ht.Add(cc, "test1");  
ht.Add(cc2, "test2");  
ht.Add(cc3, "test3");   
//cc.x = 5;  
foreach (var item in ht.Keys)  
{  
  Console.WriteLine(item.ToString());  
  Console.WriteLine(ht[item]);  
}  
Console.Read(); 
Hashtable ht = new Hashtable();
Class3 cc = new Class3(2, 3);
Class3 cc2 = new Class3(1, 4);
Class3 cc3 = new Class3(3, 3);
ht.Add(cc, "test1");
ht.Add(cc2, "test2");
ht.Add(cc3, "test3");
//cc.x = 5;
foreach (var item in ht.Keys)
{
   Console.WriteLine(item.ToString());
   Console.WriteLine(ht[item]);
}

Console.Read();

下面是输出的情况

当向Hashtable里插入cc时,这时候哈希表是空的,所以只需要判断hashcode就行了;

当cc2插入哈希表时,判断哈希码,由于已经有了一个相同的哈希码的项,所以这时候需要判断它俩是不是相同的对象,不相同再插入哈希表。

输出的时候,

注意cc2那一项判断了两次Equals,这是由于按照哈希码查找到两个项,再通过key的判断取出这项的值(key是按照插入的先后顺序排列,对比的时候也是从前向后)。

从上面的讨论可以看出,哈希码只有在作为集合索引的时候才起作用,平时根本用不上这个功能,GetHashCode方法其实不用放在Object里面,而是可以单独放在一个接口里面。

关于C#的GetHashCode相关推荐

  1. Enum.GetHashCode()的问题

    先说一下,正常如果代码可以定义成枚举,我是比较倾向于定义成枚举的,类似这样: public enum Gender{/// <summary>/// 男/// </summary&g ...

  2. 不可小瞧的GetHashCode函数

    要实现对象的相等比较,需要实现IEquatable<T>,或单独写一个类实现IEqualityComparer<T>接口. 像List<T>的Contains这样的 ...

  3. C# Note27: GetHashCode方法

    详析GetHashCode方法 转载于:https://www.cnblogs.com/carsonzhu/p/7451286.html

  4. GetHashCode() 的研究

    有个实体类.比如 1 public class Customer 2 { 3     public int ID{get;set;} 4      5     public string Name{g ...

  5. NET问答: 重写了 Equals,还有必要重写 GetHashCode 吗?

    咨询区 David Basarab: 直入主题,参考如下代码: public class Foo {public int FooId { get; set; }public string FooNam ...

  6. c# datetime._C#| DateTime.GetHashCode()方法与示例

    c# datetime. DateTime.GetHashCode()方法 (DateTime.GetHashCode() Method) DateTime.GetHashCode() method ...

  7. 结构类型需要重载GetHashCode和Equals

    我比较迟钝,到现在才知道结构类型放在字典作为键时,效率是不好的,最好重载GetHashCode和Equals,那效率究竟差异有多大呢?我写了一个测试程序. ResourceServiceKey2 ke ...

  8. Equals Finalize GetHashCode GetType MemberwiseClone ReferenceEquals ToString String.IsInterned

    参考资料: http://blog.csdn.net/afgasdg/article/details/6889383 http://www.cnblogs.com/skyivben/archive/2 ...

  9. .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)

    如果你试图通过 GetHashCode 得到的一个哈希值来避免冲突,你可能要失望了.因为实际上 GetHashCode 得到的只是一个 Int32 的结果,而 Int32 只有 32 个 bit. 3 ...

最新文章

  1. C#:消息队列应用程序
  2. aws lambda_恐怕您正在考虑AWS Lambda的冷启动完全错误
  3. 110道Python面试真题和面试简历资料(附链接)
  4. Linux学习(1)-Linux几个基础命令及文件系统功能和作用
  5. 云栖大会发布全球调度算法大赛,阿里又要搞什么黑科技?
  6. CentOS7安装ipython
  7. 企业级内网的域控环境搭建教程
  8. Android 屏幕适配:最全面的解决方案
  9. php+mysql案例含源码_[源码和文档分享]基于PHP和MYSQL数据库实现的失物招领系统...
  10. spring源码:扫描bean的原理
  11. 查看dll库导出库的函数接口
  12. 浅析中国综艺的营销策略
  13. Problem D: 求三角形面积-gyy
  14. 搜索计算机文件夹的记录怎么删除,Win7如何删除“我的电脑”搜索栏里面的搜索记录...
  15. 计算机网络设计前三层实验,基于Packet Tracer的计算机网络实验设计
  16. 用tecplot作平均速度流线图
  17. c语言编程实现简单三子棋游戏
  18. 任务调度 cron使用
  19. 中国标准时间转换为年月日时分秒,指定00:00:00 或23:59:59或当下时分秒
  20. 缓存数据库Redis

热门文章

  1. python可用编程模块规模多大_哪些Python模块可用于编程竞赛?
  2. vue set方法_Vue 数据响应式
  3. 开放大学计算机应用基础第三次,江苏开放大学-计算机应用基础第三次.doc
  4. 计算机硬件设计边界,基于JTAG的计算机硬件实验系统的设计与实现.pdf
  5. 寻找最佳特征维度_寻找5种最佳设计模式书
  6. Python Matplotlib
  7. 字符串太长 pep8_Python f字符串– PEP 498 –文字字符串插值
  8. C# DateTime日期格式
  9. C++进阶教程之预存处理器
  10. C++基本语法简介,C++程序简介