基于GetHashCode的Equals是否有任何负面后果?

时间:2015-03-03 10:55:55

标签: c# .net equals gethashcode

以下代码是否正常?

public override bool Equals(object obj)
{
  if (obj == null || !(obj is LicenseType))
    return false;
  return GetHashCode() == obj.GetHashCode();
}

public override int GetHashCode()
{
  return
    Vendor.GetHashCode() ^ 
    Version.GetHashCode() ^ 
    Modifiers.GetHashCode() ^ 
    Locale.GetHashCode();
}

所有属性都是枚举/数字字段,并且是唯一定义LicenseType对象的属性。

4 个答案:

答案 0 :(得分:6)

当两个不同的对象返回相同的HashCodes时会发生什么?

毕竟,它只是一个哈希值,因此可能与对象可以拥有的整个值范围不同。

答案 1 :(得分:6)

不,the documentation非常清楚地表明:

  

您不应该假设相等的哈希码意味着对象相等。

此外:

  

两个相等的对象返回相等的哈希码。但是,反之则不然:相等的哈希码并不意味着对象相等

  

注意:

     
      
  • 不测试哈希码的相等性以确定两个对象是否相等。 (不相等的对象可以具有相同的哈希码。)要测试相等性,请调用ReferenceEqualsEquals方法。
  •   

答案 2 :(得分:1)

只有当GetHashCode对每个可能的值都是唯一的时,才可以(没有负面后果)。举一个例子,GetHashCode(16位值)的short始终是唯一的(让我们希望如此:-)),所以基于Equals GetHashCode没问题。

另一个示例,对于intGetHashCode()是整数的值,因此我们有((int)value).GetHashCode() == ((int)value)。请注意,对于short而言,这不是真的(但short的哈希码仍然是唯一的,只是它们使用更复杂的公式)

请注意帕特里克所写的内容是错误的,因为对于"用户而言,这是正确的。一个对象/类。你是"作家"对象/类的定义,因此您定义了相等的概念和哈希码的概念。如果你定义两个对象总是相等的,无论它们的价值如何,那就没关系。

public override int GetHashCode() { return 1; }
public override bool Equals(object obj) { return true; }

Equals唯一重要的rules是:

  

需要实现以确保如果Equals方法对两个对象x和y返回true,则x的GetHashCode方法返回的值必须等于为y返回的值。

     

Equals方法具有反身性,对称性和传递性......

显然,您的Equals()GetHashCode()可以使用此规则,因此可以。

出于好奇,等于运算符(==)至少有一个例外(通常你根据Equals方法定义相等运算符)

bool v1 = double.NaN.Equals(double.NaN); // true
bool v2 = double.NaN == double.NaN; // false

这是因为{75}标准中定义的NaN值与所有值不同,NaN包括。出于实际原因,Equals会返回true

答案 3 :(得分:0)

必须注意的是,如果两个对象具有相同的哈希码,则它们必须相等,这不是一个规则。

只有大约40亿个可能的哈希码,但显然有超过40亿个可能的对象。仅有超过40亿个十字符串。因此,Pigeonhole原则必须至少有两个不相等的对象共享相同的哈希码。

假设您有一个Customer对象,其中包含一系列字段,如Name,Address等。如果在两个不同的进程中使用完全相同的数据生成两个这样的对象,则它们不必返回相同的哈希代码。如果你在星期二的一个进程中创建这样一个对象,关闭它,并在星期三再次运行程序,哈希码可能会有所不同。

这在过去曾经被人咬伤过。 System.String.GetHashCode的文档特别指出,两个相同的字符串在不同版本的CLR中可以有不同的哈希码,事实上它们也是如此。不要在数据库中存储字符串哈希,并期望它们永远相同,因为它们不会成为。