在c#字典中使用基线对象GetHashCode:不可以
本文关键字:对象 GetHashCode 不可以 基线 字典 | 更新日期: 2023-09-27 18:01:34
我正在尝试使用。net库与API类的许多实例生成的异步回调,一旦在我的事件处理程序中,我需要找到这个特定事件来自哪个实例,以及我自己关于其上下文的所有信息。
第一部分很简单,因为回调的第一个参数将是发送通知的对象,只需要强制转换。但是现在我一直在寻找一种方法来将它与我自己的数据关联起来,因为该对象很少有公共属性来标识实例。
现在,我声明…
Dictionary<TheDotNetClass,MyClass>
. .它看起来工作正常,但我怀疑它只是使用了通用对象。getHashCode/比较,它可能远不安全,可能会随着时间的推移而改变,会导致太多的冲突,等等。
然而,我想不出任何替代方法来帮助我将我得到的通用对象与我与API实例相关联的所有元数据连接起来。
我是不是忽略了什么?我所做的足够安全吗?谢谢!
默认的Equals
和GetHashCode
是基于引用相等的。如果对象没有覆盖Equals
和GetHashCode
(您可以使用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
。