重写可变对象的 GetHashCode?

2023-12-31

我读过大约 10 个关于何时以及如何覆盖的不同问题GetHashCode但还有一些事情我不太明白。大多数实现GetHashCode基于对象字段的哈希码,但有人引用了GetHashCode在对象的生命周期中永远不应该改变。如果它所基于的字段是可变的,那么它如何工作?另外,如果我确实希望字典查找等基于引用相等而不是我的覆盖,该怎么办Equals?

我主要是压倒一切Equals为了便于单元测试我的序列化代码,我假设序列化和反序列化(在我的例子中为 XML)会杀死引用相等性,所以我想至少确保它的值相等性是正确的。这是重写的坏习惯吗Equals在这种情况下?基本上在大多数执行代码中我想要引用相等并且我总是使用==我不会推翻这一点。我应该创建一个新方法吗ValueEquals或其他东西而不是覆盖Equals?我曾经假设框架总是使用==并不是Equals比较事物,所以我认为重写是安全的Equals因为在我看来,它的目的是为了如果你想要有一个不同于平等的第二个定义==操作员。但从阅读其他几个问题来看,情况似乎并非如此。

EDIT:

看来我的意图不清楚,我的意思是 99% 的时间我想要普通的旧引用相等、默认行为,没有惊喜。对于非常罕见的情况,我希望具有值相等,并且我想通过使用显式请求值相等.Equals代替==.

当我这样做时,编译器建议我覆盖GetHashCode也是如此,这就是这个问题的由来。似乎有相互矛盾的目标GetHashCode当应用于可变对象时,这些对象是:

  1. If a.Equals(b) then a.GetHashCode() should == b.GetHashCode().
  2. 的价值a.GetHashCode()在一生中永远不应该改变a.

当对象是可变对象时,这些看起来自然是矛盾的,因为如果对象的状态发生变化,我们期望的值.Equals()改变,这意味着GetHashCode应该改变以匹配变化.Equals(), but GetHashCode不应该改变。

为什么会出现这样的矛盾呢?这些建议是否不适用于可变对象?可能是假设的,但可能值得一提的是,我指的是类而不是结构。

解决:

我将 JaredPar 标记为已接受,但主要用于评论交互。总结一下我从中学到的东西是,实现所有目标并避免边缘情况下可能出现的奇怪行为的唯一方法就是仅覆盖Equals and GetHashCode基于不可变字段,或实现IEquatable。这种似乎削弱了重写的用处Equals对于引用类型,据我所知,大多数引用类型通常没有不可变字段,除非它们存储在关系数据库中以用主键标识它们。


如果它所基于的字段是可变的,那么它如何工作?

这并不意味着哈希码会随着对象的变化而变化。由于您阅读的文章中列出的所有原因,这是一个问题。不幸的是,这种问题通常只出现在极端情况下。因此,开发人员往往会逃避不良行为。

另外,如果我确实希望字典查找等基于引用相等而不是我覆盖的等于,该怎么办?

只要你实现一个像这样的接口IEquatable<T>这应该不是问题。大多数字典实现都会选择一个相等比较器,其方式将使用IEquatable<T>超过 Object.ReferenceEquals。即使没有IEquatable<T>,大多数将默认调用 Object.Equals() ,然后它将进入您的实现。

基本上,在大多数执行代码中,我想要引用相等,并且我总是使用 == 并且我不会覆盖它。

如果您希望对象的行为具有值相等性,则应覆盖 == 和 != 以强制所有比较的值相等。如果用户确实想要引用相等,他们仍然可以使用 Object.ReferenceEquals。

我曾经假设框架总是使用 == 而不是 Equals 来比较事物

随着时间的推移,BCL 使用的内容发生了一些变化。现在大多数使用相等的情况都需要IEqualityComparer<T>实例并使用它来实现平等。在未指定的情况下,他们将使用EqualityComparer<T>.Default找到一个。在最坏的情况下,这将默认调用 Object.Equals

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重写可变对象的 GetHashCode? 的相关文章

随机推荐

  • 更有效地检测检查(国际象棋)

    我目前正在开发一个国际象棋引擎 该引擎到目前为止正在运行 但需要很长时间才能生成棋步 由于必须生成许多移动 因此检查检测花费的时间是迄今为止最长的 在尝试了很多事情之后我陷入了困境 并且无法真正弄清楚如何提高效率 我是这样做的 为了检查移动
  • 如何使用图形对象渲染 WPF Hwnd

    之后RenderTargetBitmap就太慢了 我尝试了一种不同的方法 不幸的是我的尝试没有成功 希望你们中的一些人能够弄清楚为什么这段代码不起作用 var myPopup new Popup var child new Grid Bac
  • 使用带有时区的 Simple DateTimeFormatter 时获取错误的解析日期

    我有以下代码 SimpleDateFormat format new SimpleDateFormat EEE MMM dd HH mm ss z yyyy String s2 Mon Oct 19 19 52 21 IST 2015 Sy
  • 等待 Future 时 Dart 超时

    如何制作一个await future持续时间不超过5秒 我需要它 因为在某些网络操作中 连接有时会产生无提示错误 因此 我的客户只是等待了几个小时而没有回复 相反 我希望它在客户端等待超过 5 秒时触发错误 我的代码可以触发错误 但仍在等待
  • 循环执行速度控制

    有没有办法控制循环的执行速度 我有一个以 30000 步循环运行的模拟 我想可视化该循环中发生的情况 如果可能的话 在其运行时控制执行速度 我有什么想法可以做到这一点吗 你可以添加一个sleep http download oracle c
  • 如何使用 WinForms (.NET) 绘制圆角矩形?

    使用C 绘制矩形 我需要首先在每个边缘绘制圆弧 然后我需要单击按钮它将在边缘绘制圆弧 我该怎么做 C 中的图形类没有用于绘制圆角矩形的内置方法 但是有多种方法可以实现此效果 答案中的链接杰伊 里格斯 https stackoverflow
  • FieldUndefined 类型的验证错误:“Query”类型中的“register”字段未定义

    我是 GrapQL 的新手 我正在尝试将它与 Spring Boot 一起使用 我可以成功进行查询 它正在返回我需要的数据 但我现在想使用突变 当他注册时 我需要向数据库添加一个用途 这是我的 schema graphqls 文件 type
  • 具有多个应用程序的 django 静态文件

    假设我有两个应用程序 富和酒吧 项目结构如下 如何确保应用程序样式不冲突 运行manage pycollectstatic当前会解散其中一个文件 管理应用程序被导入到 admin 文件夹中的收集目录中 但是我的应用程序静态数据被直接导入到主
  • Asp.net向url字符串添加参数

    我正在页面中显示已过滤项目的列表 现在我必须通过对结果分页来限制显示 所以如果我有这样的 url 参数 example com category pizza period today 其中类别和期间也可以不显示 example com pe
  • 如何在 shell 脚本中使用 ftp 删除 3 天前的文件 (Solaris OS)

    我正在编写一个脚本来创建文件 基本上是一些表的副本 并将这些文件通过 ftp 传输到远程计算机 在转储这些文件之前 还需要删除远程计算机上 3 天的旧文件 我需要帮助编写 ksh 以使用 ftp 删除远程计算机上 3 天前的文件 通常 您会
  • 应用程序部署到 Windows Phone 7 应用程序而不是 xbox live

    当我将游戏 使用 XNA C 从 Visual Studio 部署到 Windows Phone 7 设备时 它会转到应用程序区域而不是 xbox live 子目录 如果我可以这样称呼它 我知道这并不是这样的 因为示例 XNA WP7 应用
  • 如何在本机反应中同步两个 flatList 滚动位置

    正如您在上图中看到的 有一个两列的垂直列表 我开发了两个 flatList 因为我无法使用 flatList 列选项在一行上设置不同高度的照片样式 我希望两个 flatList 具有相同的滚动位置 我包装了两个 FlatList 组件来同步
  • 在 C++ 中复制到剪贴板? [复制]

    这个问题在这里已经有答案了 我想将一些字符串复制到我的 C 应用程序中的剪贴板 我怎样才能做到这一点 另外 是否也可以复制格式 谢谢 您在评论中说过您使用 Qt Qt 有类QC剪贴板 https doc qt io qt 6 qclipbo
  • 计算具有不均匀间隔样本位置的 3D 梯度的函数

    我在一卷中进行了实验观察 import numpy as np observations are not uniformly spaced x np random normal 0 1 10 y np random normal 5 2 1
  • 如何在 Xcode 中全屏显示?

    有没有办法在 Xcode 中全屏显示 与 VS net 类似 如果有的话 怎么办 FWIW 这个老问题的现代答案分为两部分 1 使用View gt Fullscreen进入全屏 并且 这样你就不会最终每个文件都有一个全屏窗口 这将是荒谬的
  • jquery“包含”代码在 chrome 上不起作用

    我使用此代码来检查网站上的语言 然后将其从下拉菜单中删除 该代码可以在 Firefox 中运行 但无法在 Chrome 上运行 并且还会停止所有其他脚本 这是代码 var mylangme location attr href if myl
  • 如何访问 Ramda.map 中的迭代索引

    我曾经写过类似的东西 map items item index gt 与洛达什 通常我不需要index但有时它是有用的 我现在要迁移到 Ramda R map item index gt items index is undefined 当
  • 使用指针相乘矩阵

    大家好 我正在尝试练习 C 中的学习指针 所以我试图将这些数组相乘 并在结果矩阵中得到全 0 如果有人可以提示我看什么或者对造成这种情况的原因提出一些建议 那就太棒了 这是代码 include
  • 除了泛型类之外,还有其他方法可以在不装箱的情况下调用结构体的接口方法吗?

    请参阅代码片段 public interface I0 void f0 public struct S0 I0 void I0 f0 public class A
  • 重写可变对象的 GetHashCode?

    我读过大约 10 个关于何时以及如何覆盖的不同问题GetHashCode但还有一些事情我不太明白 大多数实现GetHashCode基于对象字段的哈希码 但有人引用了GetHashCode在对象的生命周期中永远不应该改变 如果它所基于的字段是