以类为键的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);
}
}