2015-03-03 56 views
1

以下代码是否正常?基于GetHashCode的Equals是否有负面影响?

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对象的唯一特性。

+0

即使取决于哈希码是好的,您的GetHashCode的实现并不好,你应该看看http://stackoverflow.com/a/720282/267 – 2015-03-03 11:01:40

+0

这不是一个特别合理的哈希代码实现:http ://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/ – 2015-03-03 11:04:07

+0

的GetHashCode用作干什么的正式成员,由成员平等比较之前快速检查。一个好的hashcode实现很重要,因为像Dictionary这样的集合使用它来创建桶。字典将使用密钥的哈希码来定位合适的桶,然后使用相等来查找完全匹配。 – 2015-03-03 11:26:16

回答

6

没有,the documentation状态很清楚:

你不应该假定等于哈希码暗示对象相等。

另外:

两个对象是相等的回报相同的散列码。但是,反过来是不正确的:相等的散列码并不意味着对象平等

和:

注意:

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

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

毕竟,它只是一个散列,因此在对象可以具有的所有值范围内都可能不是独特的。

1

只要GetHashCode对于每个可能的值都是唯一的,这没关系(没有负面影响)。举个例子,short(16位值)的GetHashCode总是唯一的(让我们希望如此:-)),所以将Equals设置为GetHashCode即可。

另一个例子,对于intGetHashCode()是整数的值,所以我们有那个((int)value).GetHashCode() == ((int)value)。请注意,例如short(但仍然是short的散列码是唯一的,它们只使用更复杂的公式),但这不是真实的。

请注意,Patrick写的是错误的,因为对于对象/类的“用户”。你是对象/类的“作者”,所以你定义了相等的概念和散列码的概念。如果你定义两个对象总是相等的,无论它们的值是多少,那么就没关系。

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

为等于唯一重要rules是:

需要

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

equals方法是自反的,对称的,传递的...

显然你Equals()GetHashCode()都OK这个规则,所以他们是好的。

只是出于好奇,存在至少对于等号(==)异常(通常定义基于所述Equals方法等于运算符)

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

这是因为NaN值在所定义IEEE 754标准与所有值不同,包括NaN。出于实际原因,Equals返回true

0

必须注意,这不是一个规则,如果两个对象具有相同的散列码,那么他们必须相等。

只有四个十亿左右可能的散列码,但显然也有超过四个十亿可能的对象。仅有40多亿十个字符的字符串。因此,Pigeonhole原则必须至少有两个不相同的对象共享相同的散列码。

假设你有一个有一堆像姓名,地址字段,等等Customer对象。如果在两个不同的进程中使两个这样的对象具有完全相同的数据,则它们不必返回相同的哈希码。如果星期二在一个进程中创建了这样一个对象,关闭它,并在周三再次运行该程序,哈希代码可能会不同。

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

相关问题