【问题标题】:GetHashCode() dummy implementation if not needed如果不需要,GetHashCode() 虚拟实现
【发布时间】:2014-09-03 14:33:31
【问题描述】:

我已经阅读了大量关于正确实施 Equals()GetHashCode() 的文章。我有一些包含很多成员变量的类,我必须为此实现Equals() 方法。到现在为止还挺好。然而,当我开始实施GetHashCode() 时,我总是在寻找一个好的实施时遇到困难。我知道某些类永远不会在字典或哈希表中使用,我不想花时间编写一个好的 GetHashCode() 实现,所以我想出了以下虚拟“默认”实现:

public override int GetHashCode()
{
    Debug.Fail( "If you see this message, implement GetHashCode() properly" );

    // Always return the same value for all instances of this class. This ensures
    // that two instances which are equal (in terms of their Equals() method)
    // have the same hash code.
    return 0;
}

我想征求您的意见,这是否可行。

一方面,我不想在不必要的时候花时间实施GetHashCode()。另一方面,我希望我的代码干净有效。上述实现确保具有相同Equals() 结果的两个实例也具有相同的哈希码。当然,如果它真的被用作字典中的键,性能会很差。但是对于这种情况,您将获得调试断言。

上述方法是否有我可能遗漏的缺点?

【问题讨论】:

  • 看看这个 SO 问题。我不会说它是重复的,但它肯定是相关的:stackoverflow.com/questions/263400/…
  • 个人意见:调试和发布构建之间的显着差异(如示例中的崩溃与成功)是个坏主意。
  • @AlexeiLevenkov 这段代码在调试和发布之间没有显着差异。 Debug.Fail 是否被执行和忽略没有区别。另请参阅下面我对 Jon Skeet 回答的评论。
  • @Tobias abort/ignore 对话框(控制台/win 表单的 Debug.Fail 的默认实现)确实可以被视为“无操作”......这就是我说“个人意见”的部分原因"。

标签: c# .net hash


【解决方案1】:

如果您真的不想实现它,我建议您改为抛出异常(例如NotImplementedException) - 这样您就不仅仅是依靠Debug.Fail 工作了。如果您最终在生产环境中遇到这种情况,那么快速失败可能是最好的选择。

但老实说,一旦你实现了平等,通常真的很容易写GetHashCode (with code like this, perhaps) - 如果它不容易那就是通常表明您的 Equals 方法无论如何都会违反其合同。

请注意,GetHashCode只是用于字典 - 如果您尝试在 LINQ 中根据您的类型的键加入两个列表, 将使用GetHashCode 也是。基本上,不执行它违反了最小惊讶原则。除非您是唯一使用您的代码的人(并且您有完美的记忆力或愿意在每次使用该类型时检查),否则您应该正确实现它,IMO。

【讨论】:

  • 上述实现不依赖Debug.Fail。这只是对开发人员的一个提示,即有一些东西需要优化。 GetHashCode() 的实现/结果为 0。这总​​是有效的,尽管如果真的用作键,它的性能并不好。我知道在 LINQ 查询中可能会调用 GetHashCode(),但目前没有。如果是在未来,开发人员将获得断言,如果他忽略它,代码仍然可以工作。
  • 顺便说一句,抛出异常会违反您永远不应该在GetHashCode() 中抛出异常的规则。我以前也这样做过,但是上面的方法不需要。
  • @Tobias: GetHashCode 在你使用 Join、Distinct、GroupBy 等时被调用。如果违反了一个假设(“这个方法不会被调用”),那么我宁愿立即发现它,也不愿因为没有注意到而让它在测试中工作,然后削弱生产用途。
  • 如果我的课程没有实现Equals(),它也不能用于一些事情。如果我作为程序员使用现有类并调用 Equals() 或一些需要 Equals() 的 LINQ 查询,那么我首先必须查看类的实现以查看它是否已实现。否则我的代码可能无法正常工作。我会对GetHashCode() 做同样的事情——如果我使用类作为键,我会寻找一个实现。即使开发人员不先查看它,上述实现也始终有效。那么你的观点是表现不佳吗?
  • @Tobias:不,如果某些东西没有覆盖EqualsGetHashCode,你只会得到参考身份。是的,你需要意识到这一点。我的观点是糟糕的性能,直到它成为生产中的一个真正问题之前可能并不明显——而即使在非常小的测试用例中,抛出异常也是显而易见的。但是覆盖 GetHashCode 通常很简单,并且可以为您提供世界上最好的东西。
猜你喜欢
  • 1970-01-01
  • 2011-11-18
  • 2017-02-08
  • 2012-02-23
  • 2020-04-19
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
相关资源
最近更新 更多