.NET(C#):GetHashCode 的作用

今儿看到两位同学在讨论GetHashCode方法的执行,貌似他们的对象等同性判断挺复杂的,而又想把同样的逻辑写在GetHashCode中,然后激烈的讨论着用什么算法让GetHashCode返回的整数更具唯一性。

我觉得简而言之GetHashCode的作用就是:尽量用最快的时间对对象进行初步判断。当然这里时间的快慢和判断的深度没有具体要求,只要没有走极端就可以(比如太费时间,或者判断深度太浅)。因此没必要吧GetHashCode搞得太复杂!

还有人错误的认为字典的存储是完全靠GetHashCode的结果,显然这是不对的,GetHashCode仅返回一个int怎能胜任所有结果呢?

 

来看这个例子,这样一个类,他的GetHashCode返回整数数据的余2的结果。(仅为做示例,很显然这个GetHashCode的执行很有效率但是比较深度也太差了)

class a
{
    public int Id { get; private set; }
    public a(int i)
    {
        Id = i;
    }

    public override bool Equals(object obj)
    {
        Console.WriteLine("Equals");
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        return Id == ((a)obj).Id;
    }

        //返回余2的结果
    public override int GetHashCode()
    {
        Console.WriteLine("GetHashCode");
        return Id % 2;
    }
}

 

接着执行代码:

var o1 = new a(1); //GetHashCode返回1
var o2 = new a(2); //GetHashCode返回0
var o3 = new a(3); //GetHashCode返回1

var dic = new Dictionary<a, object>();
dic.Add(o1, 123);
Console.WriteLine("分隔符");
Console.WriteLine(dic.ContainsKey(o2));
Console.WriteLine("分隔符");
Console.WriteLine(dic.ContainsKey(o3));

 

程序输出:

GetHashCode
分隔符
GetHashCode
False
分隔符
GetHashCode
Equals
False

可以看到,当GetHashCode可以直接分辨出不相等时,Equals就没必要调用了,而当GetHashCode返回相同结果时,Equals方法会被调用从而确保判断对象是否真的相等。所以,还是那句话:GetHashCode没必要一定把对象分辨得很清楚(况且它也不可能,一个int不可能代表所有的可能出现的值),有Equals在后面做保障。GetHashCode仅需要对对象进行快速判断。

 

最后你可能有些疑惑为什么不直接用Equals非得搞个GetHashCode在前面先判断一下?这个是由于Equals方法必须把两个对象搞清楚是等于还是不等于,所以可能效率不是最优的(况且Object.Equals通常包含类型的转换,这个可以参考IEquatable或IEqualityComparer,他们支持泛型),而GetHashCode不需要绝对弄清楚是否相等所以可以优化下效率。举个最简单的例子,比较两个人是不是完全一样(一样的话代表是他的克隆人),Equals会一个细胞接一个细胞得比较,而GetHashCode可以通过判断性别,长相,声音……快速得进行判断。所以先用GetHashCode会很快的判断出许多不同的人,当然如果GetHashCode返回True(遇到了双胞胎或者克隆人),再用Equals进行彻底的比较。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值