重写GetHash $ C $下可变对象? [英] Overriding GetHashCode for mutable objects?

查看:258
本文介绍了重写GetHash $ C $下可变对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读过有关10何时和如何重写 GetHash code 不同的问题,但还是有一些我不完全得到。 GetHash code 的大多数实现都是基于对象的字段的哈希值codeS,但它一直引以为值 GetHash code 不应该在对象的生命周期变化。这是如何工作的,如果它是基于字段是可变的?另外,如果我想字典查找等是基于引用相等不是我重写等于

I've read about 10 different questions on when and how to override GetHashCode but there's still something I don't quite get. Most implementations of GetHashCode are based on the hash codes of the fields of the object, but it's been cited that the value of GetHashCode should never change over the lifetime of the object. How does that work if the fields that it's based on are mutable? Also what if I do want dictionary lookups etc to be based on reference equality not my overridden Equals?

我主要覆盖等于为了便于单元测试我的序列化code,我承担(在我的情况,以XML)序列化和反序列化杀害参考平等的,所以我要确保至少它是按值相等正确的。这是不好的做法来覆盖等于在这种情况下?基本上大部分的执行code我想引用相等,我总是用 == ,我不重写的。我是不是应该建立覆盖等于的新方法 ValueEquals 什么呢?我曾经认为,该框架总是使用 == ,而不是等于来比较的东西,所以我认为它是安全的覆盖等于,因为它似乎对我来说,它的目的是因为如果你想有一个平等的第二个定义,那就是从不同== 运营商。从阅读其他一些问题,但似乎并非如此。

I'm primarily overriding Equals for the ease of unit testing my serialization code which I assume serializing and deserializing (to XML in my case) kills the reference equality so I want to make sure at least it's correct by value equality. Is this bad practice to override Equals in this case? Basically in most of the executing code I want reference equality and I always use == and I'm not overriding that. Should I just create a new method ValueEquals or something instead of overriding Equals? I used to assume that the framework always uses == and not Equals to compare things and so I thought it was safe to override Equals since it seemed to me like its purpose was for if you want to have a 2nd definition of equality that's different from the == operator. From reading several other questions though it seems that's not the case.

编辑:

看来我的意图不清楚,我的意思是,99%的时间我想普通的旧引用相等,默认的行为,没有惊喜。对于非常罕见的情况下,我希望能有平等的价值,我想用明确要求值相等 .Equals 而不是 ==

It seems my intentions were unclear, what I mean is that 99% of the time I want plain old reference equality, default behavior, no surprises. For very rare cases I want to have value equality, and I want to explicitly request value equality by using .Equals instead of ==.

当我这样做,编译器建议我重写 GetHash code ,以及,那就是如何这个问题上来。它似乎有一个为矛盾的目标 GetHash code 时,适用于可变对象,是的那些:

When I do this the compiler recommends I override GetHashCode as well, and that's how this question came up. It seemed like there's contradicting goals for GetHashCode when applied to mutable objects, those being:

  1. 如果 a.Equals(B)然后 a.GetHash code() == b.GetHash code()
  2. a.GetHash code()的值不应该更改 A 的寿命。
  1. If a.Equals(b) then a.GetHashCode() should == b.GetHashCode().
  2. The value of a.GetHashCode() should never change for the lifetime of a.

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

These seem naturally contradicting when a mutable object, because if the state of the object changes, we expect the value of .Equals() to change, which means that GetHashCode should change to match the change in .Equals(), but GetHashCode should not change.

为什么,似乎有这个矛盾?难道这些建议并不意味着适用于可变对象?也许假设,但可能是值得一提的,我指的是类没有结构。

Why does there seem to be this contradiction? Are these recommendations not meant to apply to mutable objects? Probably assumed, but might be worth mentioning I'm referring to classes not structs.

解析:

我打标JaredPar为接受,但主要是针对评论互动。综上所述我从这里所学到的是,只有这样才能达到所有目标,并避免在极端情况可能的古怪行为是仅覆盖等于 GetHash code 基于不可变的领域,或者实施 IEquatable 。这种似乎减少的覆盖效用等于对于引用类型,从我所看到的最引用类型通常没有一成不变的领域,除非他们存储在关系型数据库与他们的主键识别它们。

I'm marking JaredPar as accepted, but mainly for the comments interaction. To sum up what I've learned from this is that the only way to achieve all goals and to avoid possible quirky behavior in edge cases is to only override Equals and GetHashCode based on immutable fields, or implement IEquatable. This kind of seems to diminish the usefulness of overriding Equals for reference types, as from what I've seen most reference types usually have no immutable fields unless they're stored in a relational database to identify them with their primary keys.

推荐答案

它并没有在这个意义上,散列code将改变为对象的变化。这是所有在您阅读文章中列出的原因的问题。不幸的是,这是问题的类型,通常只在角落里的情况下出现。因此,开发人员往往逃脱的不良行为。

How does that work if the fields that it's based on are mutable?

It doesn't in the sense that the hash code will change as the object changes. That is a problem for all of the reasons listed in the articles you read. Unfortunately this is the type of problem that typically only show up in corner cases. So developers tend to get away with the bad behavior.

只要你喜欢落实 IEquatable℃的接口; T> 这不应该是一个问题。大多数字典的实现会选择在将使用方法的相等比较 IEquatable< T> 过Object.ReferenceEquals。即使没有 IEquatable< T> ,大部分将默认调用的Object.Equals(),它将会进入到您的实现。

As long as you implement an interface like IEquatable<T> this shouldn't be a problem. Most dictionary implementations will choose an equality comparer in a way that will use IEquatable<T> over Object.ReferenceEquals. Even without IEquatable<T>, most will default to calling Object.Equals() which will then go into your implementation.

如果你希望你的对象的行为与价值相等,你应该重写==和!=强制所有的比较值相等。用户仍然可以使用Object.ReferenceEquals如果他们真的想引用相等。

If you expect your objects to behave with value equality you should override == and != to enforce value equality for all comparisons. Users can still use Object.ReferenceEquals if they actually want reference equality.

什么是BCL用途已经改变了一点随着时间的推移。现在,大多数情况下,它们使用的平等将采取的IEqualityComparer&LT; T&GT; 实例,并用它来平等。在其中一个未指定它们将使用情况 EqualityComparer&LT; T&GT; .DEFAULT 找到一个。在最坏的情况下,这将默认调用的Object.Equals

What the BCL uses has changed a bit over time. Now most cases which use equality will take an IEqualityComparer<T> instance and use it for equality. In the cases where one is not specified they will use EqualityComparer<T>.Default to find one. At worst case this will default to calling Object.Equals

这篇关于重写GetHash $ C $下可变对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆