2014-09-03 47 views
2

我已经阅读了大量正确实施Equals()GetHashCode()的文章。我有一些有很多成员变量的类,为此我必须实现一个Equals()方法。到现在为止还挺好。但是,当实施GetHashCode()时,我总是发现一个好的实现。据我所知,某些类别他们永远不会用在字典或散列表中,我不想花时间编写一个好的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()结果的两个实例也具有相同的哈希码。当然,如果它真的会被用作字典中的关键字,那么性能会很糟糕。但是对于这种情况你会得到调试断言。

上述方法有什么缺点,我可能错过了?

+0

看看这个SO问题。我不会说这是重复的,但它是绝对相关的:http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode – Konamiman 2014-09-03 14:39:28

+1

个人意见:调试和发布版本之间的显着差异(如崩溃与样本成功)是不好的主意。 – 2014-09-03 14:39:31

+0

@AlexeiLevenkov这段代码在调试和发布之间无显着差异。如果'Debug.Fail'被执行并且被忽略,则没有区别。另请参阅我对Jon Skeet的答案的评论。 – Tobias 2014-09-03 15:41:40

回答

4

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

不过说实话,一旦你已经实现了平等是通常很容易写GetHashCodewith code like this, perhaps) - 如果它容易那么这往往是你的Equals方法反正违反了合同的标志。

注意GetHashCode只是用于字典 - 如果你尝试加入的LINQ两个列表根据你的类型的密钥,即使用GetHashCode了。基本上,不执行它违反了最小惊讶的原则。除非你是只有使用你的代码的人(你有一个完美的记忆或愿意检查每次你使用的类型),你应该正确实施,IMO。

+0

以上实现不依赖于'Debug.Fail'。这对开发人员来说只是暗示有一些东西需要优化。 'GetHashCode()'的实现/结果是0.虽然如果真的用作关键字,它的性能并不好,但它总是可以工作的。我知道在LINQ查询中可能会调用'GetHashCode()',但目前情况并非如此。如果将来会有,开发人员会得到断言,如果他忽略它,代码仍然会工作。 – Tobias 2014-09-03 15:39:52

+0

顺便说一句,抛出一个异常会违反你不应该在'GetHashCode()'中抛出异常的规则。我以前曾经这样做过,但上述方法并不需要它。 – Tobias 2014-09-03 15:43:16

+0

@Tobias:如果您使用Join,Distinct,GroupBy等,则会调用GetHashCode *。如果违反了该方法(“此方法不会被调用”),那么我宁愿立即发现它,它由于没有注意而在测试中工作,然后瘫痪生产用途。 – 2014-09-03 15:55:53