英文:
Using object references vs. identifiers as collection key
问题
这里是一个场景:假设您有一个名为"MyClass"的类,它有自己的标识符。在这个示例中,可以考虑一个唯一的整数值。现在,我想使用字典来查找该类的附加信息。我可以将字典指定为Dictionary(of Integer,
我不确定第二种方法是否足够稳定。我会假设类型为
我找到了一个类似的问题这里,但那个问题没有回答我的问题。
如果我错过了现有的问题,请友好地提供链接。
谢谢,
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
如果您不覆盖Equals
和GetHashCode
,那么对象的相等性将基于引用标识。换句话说,只有当Object.ReferenceEquals(x, y)
为真时,x.Equals(y)
才为真。对于哈希码,如果x.Equals(y)
为真,那么x.GetHashCode() = y.GetHashCode()
也为真,但即使两个引用不相等,哈希码相等也是可能的(但不太可能)。垃圾回收和对象重定位不会影响这一点。
您可以在您的类中覆盖Equals
和GetHashCode
,以便根据其中的数据使对象相等 - 就像String
一样。这样,您可以查找字典中的条目,其中字典中的键是一个对象,而您提供给TryGetValue
(或索引器)的键是一个"不同但相等"的对象。如果这样做,您通常只应该基于对象的那些在对象的生命周期内不会更改的方面来确定相等性 - 或者明确说明在将对象用作字典键之后可变的方面不应更改。
覆盖Equals
和GetHashCode
,并实现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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论