简体   繁体   English

GetHashCode计算

[英]GetHashCode calculation

I'm trying to override GetHashCode to ensure uniqueness, since i use the instances as keys in a dictionary: 我试图覆盖GetHashCode以确保唯一性,因为我将实例用作字典中的键:

IDictionary<Base, int> _counts = new Dictionary<Base,int>();

The two classes I have an issue with are: 我遇到的两个类是:

class sealed First : Base
{
    public MyEnum1 value;
    public ExtrasEnum extras;

    public override int GetHashCode()
    {
        unchecked
        {
            return ((int)value* 397) ^ (int)extras;
        }   
    }

    //Other stuff
}

class sealed Second : Base
{
    public MyEnum2 value;
    public ExtrasEnum extras;

    public override int GetHashCode()
    {
        unchecked
        {
            return ((int)value* 397) ^ (int)extras;
        }            
    }

    //Other stuff
}

However. 然而。 The issue is that when the value and extras int values become the same, then the hash codes will be equal. 问题是,当valueextras int值相同时,哈希码将相等。 The calculation was the recommended one by Resharper. 该计算是Resharper推荐的计算方法。 How do i ensure that the hashcodes for theese classes does not be come the same? 我如何确保theese类的哈希码不同? Just mix it up a little with another prime number, or? 只是将它与另一个质数混合一点,或者?

EDIT: Just to explain. 编辑:只是为了解释。 I need that if to instances of First has the same value and extras values, then these two instances must be considered the same, but if an instance of First , and a instance of Second have the same int values of value and extras , then these must not be considered the same. 我需要,如果要使First实例具有相同的valueextras值,则必须将这两个实例视为相同,但是如果First的实例和Second的实例具有相同的valueextras int值,则这些不能认为是相同的。

I'm not looking into performance, but just to ensure that same class instances are equal, and different class instances are different. 我不是在研究性能,而是在确保相同的类实例相等,而不同的类实例不同。

It isn't very difficult to generate a perfect hash from enum members. 枚举成员生成完美的哈希值并不是很难。 With the assumption that they won't have more than 256 members, you can write a fast one with: 假设他们的成员不超过256个,则可以使用以下方法编写一个快速成员:

public override int GetHashCode() {
    return ((int)value << 8) ^ (int)extras; 
}

And not generate any collisions at all by writing Second.GetHashCode() as: 通过将Second.GetHashCode()编写为,根本不会产生任何冲突:

public override int GetHashCode() {
    return ((int)value << 16) ^ (int)extras; 
}

Very simple and perfect, but doesn't scale of course when you add more derived classes. 非常简单和完美,但是当您添加更多派生类时,它当然不会扩展。 It really doesn't need to, you are micro-optimizing without having any insight in how this really speeds up your code. 确实不需要,您在进行微优化时不了解如何真正提高代码速度。 Do keep in mind that a perfect hash does not avoid bucket collisions in the dictionary, the bucket index is calculated by taking the modulo of the hash code with a prime. 请记住,完美的哈希不能避免字典中的存储桶冲突,存储桶索引是通过使用带有质数的哈希码的模来计算的。 The larger the number of items in the dictionary, the larger the prime. 词典中的项目数越大,质数越大。

Just don't do this at all. 只是根本不要这样做。 And always use a profiler if you want to know if you need to anyway. 如果想知道是否仍然需要使用探查器。

I assume that you think hash codes must not collide. 我认为您认为哈希码一定不能冲突。 This is clearly impossible to ensure in general. 显然,这总体上是不可能保证的。 The following implementation of GetHashCode is always valid: return 0; GetHashCode的以下实现始终有效: return 0; . (It's just slow but not incorrect.) (这很慢,但并非不正确。)

The way to go about this is to keep this hash code computation of yours (since its fine) but to also override Equals . 进行此操作的方法是保留您的哈希码计算(从好的角度考虑),但还要覆盖Equals There you can differentiate between the two types. 在那里您可以区分两种类型。 For example by saying: 例如,说:

if (a.GetType() != b.GetType()) return false;

In case I misuderstood your concerns a literal answer to your question would be to factor in the type of the class: 万一我误解了您的顾虑,您的问题的字面答案将是考虑类的类型:

oldHashCode ^ this.GetType().GetHashCode();

(This does not ensure uniqueness, either.) (这也不能确保唯一性。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM