Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
以类为键的C#字典_C#_Class_Dictionary_Key - Fatal编程技术网

以类为键的C#字典

以类为键的C#字典,c#,class,dictionary,key,C#,Class,Dictionary,Key,我的问题基本上与和相反: 我想使用一个中等大小的类作为字典的键,字典必须通过引用而不是通过值相等来比较键。问题是,类已经实现了Equals()(它正在执行值相等-这不是我想要的) 下面是一个用于复制的小测试类: class CTest { public int m_iValue; public CTest (int i_iValue) { m_iValue = i_iValue; } public override bool Equals (object i_va

我的问题基本上与和相反:
我想使用一个中等大小的类作为字典的键,字典必须通过引用而不是通过值相等来比较键。问题是,类已经实现了
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
}
在那之后,我再也不能向字典中添加多个相等的对象了

现在,有两个结论:

  • 如果我再次删除我自己的
    GetHashCode()
    ,哈希值将再次不同,并且可以使用字典。但是,可能会出现这样的情况,即意外地为两个相等的对象提供相同的哈希代码,这将在运行时导致异常,其原因肯定永远找不到。由于这种(很少,但不是零)风险,我不能使用字典
  • 如果我像应该做的那样正确地实现了
    GetHashCode()
    ,我无论如何也不能使用字典

  • 还有什么可能仍然使用词典?

    像以前很多次一样,我在写这个问题时想到了一个解决方案

    您可以在中指定
    IEqualityComparer
    。在.net framework中有一个,但它是内部密封的,因此您需要实现自己的:

    内部类引用比较程序:IEqualityComparer其中T:class
    {
    静态引用比较程序()
    {
    Instance=newreferencecomparer();
    }
    公共静态引用比较程序实例{get;}
    公共布尔等于(TX,TY)
    {
    返回引用等于(x,y);
    }
    公共int GetHashCode(T obj)
    {
    返回System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
    }
    }
    
    使用对象之间的分隔符可以获得重复的哈希值。例如,如果x=hash(a),y=hash(b),xy=hash(c)。所以你有xy=散列(a)+散列(b)=散列(c)。因此,为了防止重复,请使用类似于“^”的分隔符,以便散列x^y=散列(a)+散列(b),而xy=散列(c)。
      public override int GetHashCode ()
      {
        return m_iValue;
      }
    
    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);
      }
    }