简体   繁体   English

.Net等效于Java的System.identityHashCode()

[英].Net equivalent of Java's System.identityHashCode()

Java's System.identityHashCode() Java的System.identityHashCode()

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). 无论给定对象的类是否覆盖hashCode(),都为给定对象返回与默认方法hashCode()返回的哈希码相同的哈希码。

That hash code is based on the object identity, so it will always be the same for the same object, no matter if the object is mutated between calls to identityHashCode() . 该哈希码是基于对象标识的,因此对于同一对象它始终是相同的,无论对象在对identityHashCode()调用之间是否发生了突变。

In addition to that, there will not be hash collisions between any two living objects (with some Java runtimes): (the former is an inaccurate statement by Oracle in the source given below, as Jai's answer shows, and as another bug report points out as well - which basically invalidates my original question...) 除此之外,任何两个活动对象(带有某些Java运行时)之间都不会发生哈希冲突:( 前者是Oracle在下面给出的源代码中的不准确陈述,正如Jai的回答所示, 另一错误报告指出以及-这基本上使我原来的问题无效...)

[...] garbage objects are readily reclaimed and the address space is reused. 垃圾对象很容易被回收,地址空间被重用。 The collisons result from address space reuse. Collisons是地址空间重用的结果。 If the original object remains live (not GCed) then you will not encounter this problem. 如果原始对象保持活动状态(未GCed),则不会遇到此问题。

Source 资源

In .Net, there is RuntimeHelpers.GetHashCode() , which fulfills the first condition, but not the second: 在.Net中,有RuntimeHelpers.GetHashCode() ,它满足第一个条件,但不满足第二个条件:

Note that GetHashCode always returns identical hash codes for equal object references. 请注意,GetHashCode始终为相同的对象引用返回相同的哈希码。 However, the reverse is not true: equal hash codes do not indicate equal object references. 但是,事实并非如此:相等的哈希码并不表示相等的对象引用。 A particular hash code value is not unique to a particular object reference; 特定的哈希码值对于特定的对象引用不是唯一的。 different object references can generate identical hash codes. 不同的对象引用可以生成相同的哈希码。

So is there anything like Java's identityHashCode() in .Net? 那么,.Net中是否有类似Java的identityHashCode()东西?

Edit: 编辑:

It was suggested that this is the same as Memory address of an object in C# which it is not, as the memory address cannot be used here (solely), as memory management moves objects around, hence the address may change during the lifetime of an object. 建议这与C#对象的内存地址相同,但与C#中的对象的内存地址不同 ,这是因为内存管理会移动对象,因此此处(仅)不能使用内存地址(因此)。宾语。

Currently Java's Object#hashCode() and System#identifyHashCode() do not ensure unique values to be returned. 当前,Java的Object#hashCode()System#identifyHashCode() 不能确保返回唯一值。 There is already questions on this, and this is an example. 对此已经存在疑问, 是一个示例。

You have mentioned a bug report which states that collision occurred because objects were garbage collected, and the same memory address is reused. 您提到了一个错误报告,该报告指出发生冲突是因为对象被垃圾回收,并且相同的内存地址被重用。 However modifying the same test case would prove otherwise: 但是,修改相同的测试用例将证明相反:

List<Object> allObjs = new ArrayList<>(); // Used to prevent GC
Set<Integer> hashes = new HashSet<Integer>(1024);

int colls = 0;
for (int n = 0; n < 100000; n++)
{
    Integer obj = new Integer(88);
    allObjs.add(obj); // keep a strong reference to prevent GC
    int ihash = System.identityHashCode(obj);
    Integer iho = Integer.valueOf(ihash);
    if (hashes.contains(iho))
    {
        System.err.println("System.identityHashCode() collision!");
        colls++;
    }
    else
    {
        hashes.add(iho);
    }
}

System.out.println("created 100000 different objects - "
        + colls
        + " times with the same value for System.identityHashCode()");

System.out.println("Size of all objects is " + allObjs.size());
System.out.println("Size of hashset of hash values is " + hashes.size());

Result: 结果:

System.identityHashCode() collision!
System.identityHashCode() collision!
System.identityHashCode() collision!
created 100000 different objects - 3 times with the same value for System.identityHashCode()
Size of all objects is 100000
Size of hashset of hash values is 99997

In the linked SO question, it was also mentioned that in some implementations of JRE, the rate of collision is greatly reduced . 在链接的SO问题中,还提到了在JRE的某些实现中,冲突率大大降低了 However, it does seem like no implementation has managed to prevent all collisions. 但是,似乎没有实现能够防止所有冲突。 Therefore, there is no way of ensuring uniqueness of hash codes even in Java. 因此,即使在Java中,也无法确保哈希码的唯一性。

Therefore, don't simply believe based on one source. 因此,不要简单地相信一个来源。 The person commenting it is also just a member of the Oracle team, and he or she is most likely not the person designing this. 评论它的人也只是Oracle团队的成员,而他或她很可能不是设计它的人。

In both C# and Java, you would have to create your own unique number generator of some kind. 在C#和Java中,您都必须创建自己的某种独特的数字生成器。 So the solution provided by NPras seems to do that for .NET. 因此,NPras提供的解决方案似乎适用于.NET。

I would refer you to the following answer from Eric Lippert (who was part of the C# language design & compiler team) where he suggested using ObjectIDGenerator. 我想请您参考Eric Lippert (他是C#语言设计和编译器团队的成员)的以下回答 ,他在其中建议使用ObjectIDGenerator。

To generate unique ids for objects you could use the aptly named ObjectIDGenerator that we conveniently provide for you 要为对象生成唯一的ID,您可以使用我们方便地为您提供的适当命名的ObjectIDGenerator

Looking at the reference source (good thing they open-sourced the framework now), it does use RuntimeHelpers.GetHashCode() but also handles the potential collision by storing the references separately. 查看参考源 (好消息是他们现在开放了框架的源代码),它确实使用RuntimeHelpers.GetHashCode()但也通过单独存储参考来处理潜在的冲突。

Do note his warning about object lifetime. 请注意他关于对象寿命的警告。 If you need it for transient objects, he suggested you reimplement the generator - which is now much easier that you have access to the source. 如果您需要临时对象,他建议您重新实现生成器-现在可以更轻松地访问源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM