GetHashCode()
似乎有些敌意.我从评论中得到的印象是,一些C#开发人员不认为你应该经常覆盖GetHashCode() – 当然有些评论者似乎认为一个帮助获得行为的图书馆是无用的.这样的功能被认为对于
Java community to ask for it to be added to the JDK在Java中是有用的,而且是
now in JDK 7.
有没有一些根本原因,在C#中,您不需要 – 或绝对不应该像Java一样经常覆盖GetHashCode()(相应地,Equals())我发现自己经常使用Java,例如,每当我创建一个类型,我知道我想保留在一个HashSet或用作一个键在HashMap(等效的.net字典).
解决方法
编写一个类型以用作在Dictionary / HashMap中使用的复合键是很常见的.通常这种类型,你需要value equality (equivalence) as opposed to reference equality(identity),例如:
IDictionary<Person,IList<Movie> > moviesByActor; // e.g. initialised from DB // elsewhere... Person p = new Person("Chuck","Norris"); IList<Movie> chuckNorrisMovies = moviesByActor[p];
在这里,如果我需要创建一个新的Person实例来执行查找,我需要Person来实现值等式,否则它将不匹配Dictionary中的现有条目,因为它们具有不同的身份.
为了获得值相等性,您需要以两种语言覆盖Equals()和GetHashCode().
C#的结构(值类型)implement value equality为您提供(尽管潜在效率低下),并提供了一致的GetHashCode实现.这可能足以满足许多人的需求,除非性能问题另有规定,否则他们不会进一步实施自己的改进版本.
Java没有这样的内置语言功能.如果要创建一个具有值相等语义的类型作为复合键,则必须自己实现equals()和相应的hashCode(). (有第三方帮助和图书馆可以帮助您做到这一点,但没有内置于语言本身).
我将C#值类型描述为“可能无效率”,用于“词典”,因为:
> The implementation of ValueType.Equals
itself can sometimes be slow.这是用于字典查找.
> ValueType.GetHashCode的实现虽然正确,但可以产生许多冲突,导致非常差的字典性能.看看this answer to a Q by Jon Skeet,这表明KeyValuePair< ushort,uint>似乎总是产生相同的hashCode!