使用对象引用与标识符作为集合键

huangapple go评论85阅读模式
英文:

Using object references vs. identifiers as collection key

问题

这里是一个场景:假设您有一个名为"MyClass"的类,它有自己的标识符。在这个示例中,可以考虑一个唯一的整数值。现在,我想使用字典来查找该类的附加信息。我可以将字典指定为Dictionary(of Integer, )),或者使用对象类型本身作为键。然后,字典将是Dictionary(of , ))。

我不确定第二种方法是否足够稳定。我会假设类型为的键将转换为指向指定为键的对象的引用。如果是这样的话,那么它将再次是一个整数(我会猜测)。在性能方面,两种方法应该是相同的。但我担心引用可能会因为内存紧缩而改变,就像这里提到的那样。如果是这样的话,存储在字典中的引用将变为无效。因此,在某种情况下,我会找到特定的字典项,而在内存紧缩后的另一种情况下,我将无法找到相同的对象,因为它的引用已经改变了。(我不知道如何更简洁地解释这个问题,但我希望你明白我的意思。)

我找到了一个类似的问题这里,但那个问题没有回答我的问题。
如果我错过了现有的问题,请友好地提供链接。

谢谢,
Sascha

英文:

is it safe to use an object referece as dictionary key or sould I use some identifier?

Here is the scenario: suppose you have a class "MyClass" with it's own identfier. For the example think of a unique integer value. Now I want to lookup additional information for that class using a dictionary. I could specify the dictionary as Dictionary(of Integer, <sometype>)) or the use the object type itself as key. Then the dictionary would be Dictionary(of <MyClass>, <sometype>).

I am not sure if the second approach is stable enough. I would assume that a key of type <MyClass> will translate to a reference pointing to the object specified as key. If so, then that will be an integer again (I would guess). With respect to performance both approaches should then be the same. But I am concerned that refrences could change due to memory compaction like mentioned here. If that is true, the reference stored in the dictionary would be invalid. So in one case I would find a certain dictionary item and in another case after the memory compaction I would fail to find the same object because its reference changed. (I don't know how to explain this any shorter, but I hope, you get the point.)

I found a similar question here, but that doesn't answer my question.
If I missed an existing question, please kindly post a link.

Thanks,
Sascha

答案1

得分: 4

如果您不覆盖EqualsGetHashCode,那么对象的相等性将基于引用标识。换句话说,只有当Object.ReferenceEquals(x, y)为真时,x.Equals(y)才为真。对于哈希码,如果x.Equals(y)为真,那么x.GetHashCode() = y.GetHashCode()也为真,但即使两个引用不相等,哈希码相等也是可能的(但不太可能)。垃圾回收和对象重定位不会影响这一点。

可以在您的类中覆盖EqualsGetHashCode,以便根据其中的数据使对象相等 - 就像String一样。这样,您可以查找字典中的条目,其中字典中的键是一个对象,而您提供给TryGetValue(或索引器)的键是一个"不同但相等"的对象。如果这样做,您通常只应该基于对象的那些在对象的生命周期内不会更改的方面来确定相等性 - 或者明确说明在将对象用作字典键之后可变的方面不应更改。

覆盖EqualsGetHashCode,并实现IEquatable(Of T)是相当常见的,但这并不意味着这总是正确的做法。这通常适用于相对“原始”的类型,而不是特定于业务的类型 - 例如,适用于Point而不是Customer。但这只是一般指导 - 您应该根据您的具体情况权衡利弊。

英文:

If you don't override Equals and GetHashCode, then you'll end up with equality based on reference identity. In other words, x.Equals(y) will be true if and only if Object.ReferenceEquals(x, y) is true. For hash codes, x.GetHashCode() = y.GetHashCode() will be true if x.Equals(y) is true, but it's possible (but unlikely) for the hash codes to be equal even if the two references are not equal. Garbage collection and object relocation does not affect this.

You could also override Equals and GetHashCode in your class, to make objects equal based on the data within them - just like String does. That way you could look up an entry in the dictionary where the key in the dictionary is one object, and the key you're providing to TryGetValue (or the indexer) is a "different but equal" object. If you do this, you should usually only base equality on aspects of your object which can't change over the object's lifetime - or clearly document that the mutable aspects should not be changed after using the object as a dictionary key.

It's reasonably common to override Equals and GetHashCode, and also implement IEquatable(Of T) - but that doesn't mean it's always the right thing to do. It's usually appropriate for reasonably "primitive" types rather than business-specific types - e.g. for Point rather than Customer. But that's only general guidance - you should think of the pros and cons for your specific situation.

huangapple
  • 本文由 发表于 2020年1月3日 16:35:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/59575374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定