代码之家  ›  专栏  ›  技术社区  ›  Sascha

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

  •  1
  • Sascha  · 技术社区  · 4 年前

    使用对象引用作为字典键安全吗?还是应该使用一些标识符?

    下面是一个场景:假设您有一个带有自己标识符的类“MyClass”。例如,考虑一个唯一的整数值。现在我想使用字典查找该类的其他信息。我可以将字典指定为dictionary(对于整数,<sometype>)或者使用对象类型本身作为键。那么字典就是字典(属于<MyClass>,<sometype>)。

    我不确定第二种方法是否足够稳定。我会假设一个类型为<MyClass>将转换为指向指定为键的对象的引用。如果是这样的话,那么这将再次是一个整数(我猜)。就性能而言,两种方法应该是相同的。但我担心的是,参考文献可能会因上述记忆压缩而改变 here .如果这是真的,字典中存储的引用将无效。因此,在一种情况下,我会找到某个字典项,在另一种情况下,在内存压缩后,我会找不到同一个对象,因为它的引用发生了变化。(我不知道如何更简短地解释这一点,但我希望你能理解。)

    我发现了一个类似的问题 here ,但这并不能回答我的问题。 如果我错过了一个现有的问题,请发一个链接。

    谢谢 萨沙

    1 回复  |  直到 4 年前
        1
  •  4
  •   Jon Skeet    4 年前

    如果你不重写 Equals GetHashCode ,那么您将得到基于引用标识的等式。换句话说, x.Equals(y) 当且仅当 Object.ReferenceEquals(x, y) 这是真的。对于散列码, x.GetHashCode() = y.GetHashCode() 如果 x、 等于(y) 这是真的,但事实并非如此 可能的 (但不太可能)即使两个引用不相等,哈希码也相等。垃圾收集和对象重新定位不会影响这一点。

    能够 也覆盖 等于 方法 在类中,根据对象中的数据使对象相等,就像 String 做这样,你可以在字典中查找一个条目,其中字典中的键是一个对象,而你提供给它的键是一个对象 TryGetValue (或索引器)是“不同但相等”的对象。如果你这么做,你应该 通常 只有在对象的生命周期内不能改变的方面,或者清楚地记录可变方面应该改变的方面,才能建立平等 将该对象用作字典键后,将被更改。

    这是相当常见的覆盖 等于 方法 ,并实施 IEquatable(Of T) -但这并不意味着这总是正确的做法。它通常适用于合理的“原始”类型,而不是特定于业务的类型,例如 Point 而不是 Customer .但这只是一般性的指导——你应该针对自己的具体情况考虑利弊。