簡體   English   中英

以類為鍵的 C# 字典

[英]C# Dictionary with a class as key

我的問題基本上與Dictionary.ContainsKey 返回 False相反,但是當使用自定義類作為鍵時,想要 True並且“字典中不存在給定的鍵”錯誤
我想使用一個中等大小的類作為字典的鍵,並且字典必須通過引用而不是值相等來比較鍵。 問題是,該類已經實現了Equals() (它正在執行值相等 - 這不是我在這里想要的)。

這是一個用於復制的小型測試類:

class CTest
{
  public int m_iValue;

  public CTest (int i_iValue)
  {
    m_iValue = i_iValue;
  }

  public override bool Equals (object i_value)
  {
    if (ReferenceEquals (null, i_value))
      return false;
    if (ReferenceEquals (this, i_value))
      return true;

    if (i_value.GetType () != GetType ())
      return false;

    return m_iValue == ((CTest)i_value).m_iValue;
  }

}

我還沒有實現GetHashCode() (實際上我已經實現了,但到目前為止它只返回base.GetHashCode() )。

現在我創建了一個帶有字典的測試程序,該字典使用此類的實例作為鍵。 我可以毫無問題地向字典添加多個相同的實例,但這只是因為GetHashCode()返回不同的值才有效:

private static void Main ()
{
  var oTest1 = new CTest (1);
  var oTest2 = new CTest (1);
  bool bEquals = Equals (oTest1, oTest2);   // true
  var dict = new Dictionary<CTest, int> ();
  dict.Add (oTest1, 1);
  dict.Add (oTest2, 2);         // works
  var iValue1 = dict[oTest1];   // correctly returns 1
  var iValue2 = dict[oTest2];   // correctly returns 2
  int iH1 = oTest1.GetHashCode ();   // values different on each execution
  int iH2 = oTest2.GetHashCode ();   // values different on each execution, but never equals iH1
}

並且每次的哈希值都不同,可能是因為object.GetHashCode()的計算使用了一些隨機化或一些來自引用句柄的數字(每個對象都不同)。
但是,這個答案為什么在覆蓋 Equals 方法時覆蓋 GetHashCode 很重要? GetHashCode()必須為相等的對象返回相同的值,所以我添加了

  public override int GetHashCode ()
  {
    return m_iValue;
  }

之后,我無法再向字典中添加多個相等的對象。

現在,有兩個結論:

  1. 如果我再次刪除自己的GetHashCode() ,哈希值將再次不同,並且可以使用字典。 但是可能存在不小心給兩個相等的對象賦予相同的哈希碼的情況,這會在運行時導致異常,其原因肯定永遠不會被找到。 由於這種(很小但不是零)風險,我不能使用字典。
  2. 如果我像我應該做的那樣正確地實現了GetHashCode() ,無論如何我都不能使用字典。

仍然使用字典的可能性有多大?

像以前很多次一樣,我在寫這個問題時就有了解決方案的想法。

您可以在字典構造函數中指定一個IEqualityComparer<TKey> .net 框架中有一個,但它是internal sealed ,因此您需要實現自己的:
.NET 中是否有任何類型的“ReferenceComparer”?

internal class ReferenceComparer<T> : IEqualityComparer<T> where T : class
{
  static ReferenceComparer ()
  {
    Instance = new ReferenceComparer<T> ();
  }

  public static ReferenceComparer<T> Instance { get; }

  public bool Equals (T x, T y)
  {
    return ReferenceEquals (x, y);
  }

  public int GetHashCode (T obj)
  {
    return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj);
  }
}

暫無
暫無

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

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