如果您查看MSDN 文档,您会发现以下有关GetHashCode方法的默认行为的说明:
如果未覆盖 GetHashCode,则通过调用基类的 Object.GetHashCode 方法计算引用类型的哈希码,该方法根据对象的引用计算哈希码;有关详细信息,请参阅 RuntimeHelpers.GetHashCode。换句话说,ReferenceEquals 方法为其返回 true 的两个对象具有相同的哈希码。如果值类型不覆盖 GetHashCode,则基类的 ValueType.GetHashCode 方法使用反射根据类型字段的值计算哈希码。换句话说,字段具有相同值的值类型具有相同的哈希码
根据我的理解,我们可以假设:
重要编辑
正如上面的一条评论所指出的,.NET 垃圾收集器可以决定在对象生命周期内移动对象在内存中的物理位置,换句话说,对象可以在托管内存中“重定位”。
这是有道理的,因为垃圾收集器负责管理创建对象时分配的内存。
经过一些搜索并根据this stackoverflow question(阅读用户@supercat提供的评论)似乎这种重定位在其生命周期内不会更改对象实例的哈希码,因为哈希码计算一次(第一次它的值被请求)并且计算出的值被保存并稍后重用(当再次请求哈希码值时)。
总而言之,根据我的理解,您唯一可以假设的是,给定指向内存中同一对象的两个引用,它们的哈希码将始终相同。换句话说,如果 Object.ReferenceEquals(a, b) 则 a.GetHashCode() == b.GetHashCode()。此外,似乎给定一个对象实例,它的哈希码将在其整个生命周期内保持不变,即使垃圾收集器更改了对象的物理内存地址。
关于哈希码使用的旁注
务必记住,在 .NET 框架中引入哈希码的唯一目的是处理哈希表数据结构。
为了确定用于给定值的桶,取相应的键并计算其哈希码(准确地说,桶索引是通过对 GetHashCode 调用返回的值应用一些规范化来获得的,但是细节对本次讨论不重要)。换句话说,哈希表的 .NET 实现中使用的哈希函数基于键的哈希码的计算。
这意味着哈希码的唯一安全用法是平衡哈希表,正如 Eric Lippert在这里指出的那样,所以不要为了任何其他目的编写依赖于哈希码值的代码。
归档时间: |
|
查看次数: |
231 次 |
最近记录: |