簡體   English   中英

基於GetHashCode等於是否有負面影響?

[英]Is there any negative consequence in having Equals based on 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對象的唯一屬性。

當兩個不同的對象返回相同的HashCode時會發生什么?

畢竟,它只是一個散列,因此在對象可以具有的所有值的范圍內可能並沒有區別。

不, 文檔中非常清楚地指出:

您不應假定相等的哈希碼表示對象相等。

也:

相等的兩個對象返回相等的哈希碼。 但是,事實並非如此: 相等的哈希碼並不意味着對象相等

和:

警告:

  • 不要測試哈希碼是否相等,以確定兩個對象是否相等。 (不相等的對象可以具有相同的哈希碼。)要測試是否相等,請調用ReferenceEqualsEquals方法。

僅當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; }

等於的唯一重要規則是:

需要實現以確保如果Equals方法為兩個對象x和y返回true,則GetHashCode方法為x返回的值必須等於為y返回的值。

等於方法是自反的,對稱的和可傳遞的...

顯然,使用此規則可以使您的Equals()GetHashCode()正常,因此它們也可以。

出於好奇,至少有一個等於運算符( == )的例外(通常您基於Equals方法定義等於運算符)

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

這是因為NaN值在IEEE 754標准中定義為不同於NaN包括的所有值。 出於實際原因, Equals返回true

必須注意的是,如果兩個對象具有相同的哈希碼,則它們必須相等是不規則的。

大概只有40億個哈希碼,但是顯然有超過40億個可能的對象。 僅十個字符的字符串就遠遠超過40億個。 因此,根據鴿孔原理,必須至少有兩個不相同的對象共享相同的哈希碼。

假設您有一個Customer對象,該對象具有一堆字段,例如Name,Address等。 如果在兩個不同的過程中使用完全相同的數據制作兩個這樣的對象,則它們不必返回相同的哈希碼。 如果您在一個星期二通過一個進程創建了這樣的對象,將其關閉,然后在星期三再次運行該程序,則哈希碼可能會有所不同。

過去這已經傷了人們。 System.String.GetHashCode的文檔特別指出,兩個相同的字符串在不同版本的CLR中可以具有不同的哈希碼,實際上,它們確實可以。 不要將字符串哈希存儲在數據庫中,並希望它們永遠一樣,因為它們不會一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM