在c#字典中使用基线对象GetHashCode:不可以

本文关键字:对象 GetHashCode 不可以 基线 字典 | 更新日期: 2023-09-27 18:01:34

我正在尝试使用。net库与API类的许多实例生成的异步回调,一旦在我的事件处理程序中,我需要找到这个特定事件来自哪个实例,以及我自己关于其上下文的所有信息。

第一部分很简单,因为回调的第一个参数将是发送通知的对象,只需要强制转换。但是现在我一直在寻找一种方法来将它与我自己的数据关联起来,因为该对象很少有公共属性来标识实例。

现在,我声明…

Dictionary<TheDotNetClass,MyClass> 

. .它看起来工作正常,但我怀疑它只是使用了通用对象。getHashCode/比较,它可能远不安全,可能会随着时间的推移而改变,会导致太多的冲突,等等。

然而,我想不出任何替代方法来帮助我将我得到的通用对象与我与API实例相关联的所有元数据连接起来。

我是不是忽略了什么?我所做的足够安全吗?谢谢!

在c#字典中使用基线对象GetHashCode:不可以

默认的EqualsGetHashCode是基于引用相等的。如果对象没有覆盖EqualsGetHashCode(您可以使用dotPeek之类的反编译器进行验证),那么每个对象实例将是一个唯一的字典键,因此,您可以使用Dictionary向每个实例附加额外的数据。这是一个相当常见的场景,并且它是完全支持的——您正在按照设计使用它。

我不会担心哈希冲突。BCL团队很聪明;他们设计了基本的GetHashCode作为哈希键,所以碰撞应该是最小的。

Edit:这是一个代码片段,显示哈希码不是基于对象的地址。压缩后,b的地址会改变,但注意它的哈希码不会改变。

var a = new object();
var originalHashCodeA = a.GetHashCode();
for (var i = 0; i < 10000; ++i)
    new object();
var b = new object();
var originalHashCodeB = b.GetHashCode();
// Synchronous garbage collection (see http://stackoverflow.com/q/748777/87399)
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine(a.GetHashCode() == originalHashCodeA);
Console.WriteLine(b.GetHashCode() == originalHashCodeB);

注意输出是True, True。在垃圾收集和压缩之后,两个对象的哈希码都没有改变。所以,默认的GetHashCode是安全的跨压缩

这个方法很好。只有当Object.Equals返回true时,两个哈希码才会匹配(假设类实现正确)。

如果该函数返回true,那么我可以想象您希望"碰撞"发生,因为它们实际上是相同的对象。注意,当您使用自定义类时,建议您为此重写.Equals.GetHashCode