Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# GetHashCode是否应取决于类型?_C#_Inheritance_Gethashcode - Fatal编程技术网

C# GetHashCode是否应取决于类型?

C# GetHashCode是否应取决于类型?,c#,inheritance,gethashcode,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 doubl

首先,我使用所描述的
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)
    {

    }
}
如果我有一个
Foo
和一个
DerivedFoo
对于每个属性都有相同的值,那么它们将有相同的哈希代码。这意味着我可以使用
HashSet
或在Linq中使用
Distinct
方法,这两个实例将被视为相同

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

顺便说一句,我意识到与这个主题相关的问题很多,但我还没有发现一个问题可以直接回答这个问题。

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

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

如果两个对象具有相同的哈希代码,则调用
Equals()
方法查看它们是否相同。由于类型不同(当然,这取决于您如何编写Equals重载),它们将不相等,因此也可以

即使每种类型有不同的散列码算法,也总是有冲突的可能,因此也需要进行
Equals()
检查

现在给出上面的示例,您没有实现
Equals()
这将使每个对象都不同,而不管哈希代码是什么,因为
object
Equals()
的默认实现是一个引用相等检查

如果没有,请继续为每个类型重写
Equals()
(如果愿意,它们可以继承
GetHashCode()
的实现,或者有新的实现),并且在声明它们相等之前,可以确保compare-to对象的类型相同。并确保始终实现
Equals()
GetHashCode()
,以便:

  • Equals()
    的对象必须具有相同的
    GetHashCode()
    结果
  • 具有不同
    GetHashCode()
    的对象必须不是
    Equals()

这两个实例不需要有不同的哈希代码。HashSet或其他框架类不会假定GetHashCode的结果,因为即使在类型中也可能存在冲突。GetHashCode仅用于确定哈希表中存储项的位置。如果HashSet中存在冲突,那么它将依靠Equals方法的结果来确定唯一匹配。这意味着在实现GetHashCode时,还应该实现Equals(并检查类型是否匹配)。类似地,无论何时实现Equals,都应该实现GetHashCode。请参阅Eric Lippert的一个很好的解释。

感谢您提供的信息,我没有意识到如果存在哈希冲突,会进行等于检查。你知道我在哪里可以找到一些文档来支持这一点吗?Eric Lippert在@Brent的博客文章中提到了这一点,这是一个很好的开始:主要的一点是a)Equals()应该确保两个实例都是相同的类型,b)Equals()应该始终至少检查哈希代码中使用的相同字段(以免相同对象的哈希代码不同,这是不好的)。