GetHashCode应该取决于类型吗?

Ric*_*chK 3 c# inheritance gethashcode

首先,我在这里使用所GetHashCode描述的算法.现在,想象下面的(人为的)示例:

class Foo
{
    public Foo(int intValue, double doubleValue)
    {
        this.IntValue = intValue;
        this.DoubleValue = doubleValue;
    }

    public int IntValue { get; private set; }
    public double DoubleValue { get; private set; }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + IntValue.GetHashCode();
            hash = hash * 23 + DoubleValue.GetHashCode();
            return hash;
        }

    }
}

class DerivedFoo : Foo
{
    public DerivedFoo(int intValue, double doubleValue)
       : base(intValue, doubleValue)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

如果我有一个Foo和一个DerivedFoo具有相同值的每个属性,它们将具有相同的哈希码.这意味着我可以拥有HashSet<Foo>或使用DistinctLinq中的方法,这两个实例将被视为相同.

我可能只是误解了使用GetHashCode但我希望这两个实例有不同的哈希码.这是无效的期望还是应该GetHashCode在计算中使用类型?(或者DerivedClass还应该覆盖GetHashCode)?

PS我意识到关于这个主题的SO有很多很多问题,但是我没有发现直接回答这个问题的问题.

Jam*_*are 6

GetHashCode() 不应该保证唯一性(尽管如果尽可能独特,它有助于提高性能).

主要规则GetHashCode()是等效对象必须具有相同的哈希代码,但这并不意味着非等效对象不能具有相同的哈希代码.

如果两个对象具有相同的哈希码,Equals()则调用该方法以查看它们是否相同.由于类型不同(取决于你如何编码你的Equals过载),它们将不相等,因此它会没问题.

甚至如果你有一个不同的散列码算法为每种类型的,还是有总是碰撞的机会,因此需要对Equals()检查为好.

现在给出上面的示例,您不实现Equals()这将使每个对象都不同,无论哈希代码如何,因为Equals()from 的默认实现object是引用相等性检查.

如果还没有,请继续并覆盖Equals()每个类型(GetHashCode()如果你愿意,可以继承你的实现,或者有新的),你可以确保compare-to对象的类型是在宣布他们平等之前一样.并确保Equals()GetHashCode()始终实施,以便:

  • Equals() 必须具有相同GetHashCode()结果的对象.
  • 与不同的对象GetHashCode()一定不能Equals().