C# 如何在没有任何ID的类中实现GetHashCode

C# 如何在没有任何ID的类中实现GetHashCode,c#,hashset,gethashcode,C#,Hashset,Gethashcode,比如我有课 class Person { public string FirstName { get; set; } public string LastName { get; set; } } 如何在此类中重写GetHashCode?您可以执行以下操作: public override int GetHashCode() { return String.Concat(FirstName, LastName).GetHashCode(); }

比如我有课

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

如何在此类中重写GetHashCode?

您可以执行以下操作:

public override int GetHashCode()
    {
        return String.Concat(FirstName, LastName).GetHashCode();
    }
public override int GetHashCode()
{
    return FirstName.GetHashCode() ^ LastName.GetHashCode()
}

查看更多信息

您可以执行以下操作:

public override int GetHashCode()
{
    return FirstName.GetHashCode() ^ LastName.GetHashCode()
}

检查更多信息您应该将对象的hashcode计算基于不可变字段,如果您可以使
Person
的FirstName和LastName字段不可变,则可以根据Josh Bloch的建议使用以下模式:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + FirstName.GetHashCode();
    hash = hash * 31 + LastName.GetHashCode();
    return hash;
}

您应该将对象的hashcode计算基于不可变字段,如果可以使
Person
的名字和姓氏字段不可变,则可以根据Josh Bloch的建议使用以下模式:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + FirstName.GetHashCode();
    hash = hash * 31 + LastName.GetHashCode();
    return hash;
}


这是一个非常糟糕的方法<代码>名字=ab;SecondName=cd与
FirstName=a不同;SecondName=bcd
并且不应该给出相同的哈希代码。这称为冲突,它们没有什么不好的。不想经常发生碰撞吗?为你的孩子使用真名,不要只考虑所有选项。碰撞肯定有一些不好的地方,它们永远都不可取。当你可以很容易地避开它们时,情况就更糟了。“真名”到底是什么
Rob
Robert
都是有效的名字,不难发现因为姓氏而发生冲突的情况。不要写坏代码,然后责怪用户。考虑到课程目的,上述冲突(
ab
cd
v.
abc
d
)是不可能发生的。代码的错误在于
String.Concat(FirstName,LastName)
-它占用了太多的计算资源。哈希应该快速计算。正确,我们应该避免冲突,但由于哈希代码是有限的数字,为了避免冲突,我们必须将冲突转移到不真实或罕见的值。这就是你的例子——不真实的情况,这是一个很好的碰撞,减少了来自真实人物的碰撞。你有没有注意到,这个类是人,而不是一个可以用1个字母或2个字母来定义的字符串。这是一个非常糟糕的方法<代码>名字=ab;SecondName=cd与
FirstName=a不同;SecondName=bcd
并且不应该给出相同的哈希代码。这称为冲突,它们没有什么不好的。不想经常发生碰撞吗?为你的孩子使用真名,不要只考虑所有选项。碰撞肯定有一些不好的地方,它们永远都不可取。当你可以很容易地避开它们时,情况就更糟了。“真名”到底是什么
Rob
Robert
都是有效的名字,不难发现因为姓氏而发生冲突的情况。不要写坏代码,然后责怪用户。考虑到课程目的,上述冲突(
ab
cd
v.
abc
d
)是不可能发生的。代码的错误在于
String.Concat(FirstName,LastName)
-它占用了太多的计算资源。哈希应该快速计算。正确,我们应该避免冲突,但由于哈希代码是有限的数字,为了避免冲突,我们必须将冲突转移到不真实或罕见的值。这就是你的例子——不真实的情况,这是一个很好的碰撞,减少了来自真实人物的碰撞。你注意到了吗,这个类是Person,而不是两个stringsthatscandistinctby1or2letters你的链接指向一个不同的问题:“当两个字符串都可互换时”你的链接指向一个不同的问题:“当两个字符串都可互换时”…当
FirstName
为空时,实现失败…另一个问题是整数溢出(
31*hash
很可能超过
int.MaxValue
)。为了防止这种情况,使用
unchecked{…}
@DmitryBychenko对计算进行检查,这两点都是正确的,但是为了简单起见,在小样本中通常会忽略错误检查,以获得要点。这不需要不变性。不变性是确保对象在基于哈希的结构中使用时不发生更改的一种好方法,但如果在此期间不进行更改,可变对象也会在基于哈希的结构中工作。@GrigorAleksanyan,是的,哈希代码可能会发生冲突,
int
可以有2^32个不同的值,这意味着所有字符串都有2^32个哈希代码,但可能的字符串数量是无限的,因此最终可能会发生一些冲突,您无法阻止这种情况。然而,我们的目标是增加唯一性的可能性,而上述公式(乘以素数)在执行时做得很好……并且每当
FirstName
为空时,实现就会失败……另一个问题是整数溢出(
31*hash
可能会远远超过
int.MaxValue
)。为了防止这种情况,使用
unchecked{…}
@DmitryBychenko对计算进行检查,这两点都是正确的,但是为了简单起见,在小样本中通常会忽略错误检查,以获得要点。这不需要不变性。不变性是确保对象在基于哈希的结构中使用时不发生更改的一种好方法,但如果在此期间不进行更改,可变对象也会在基于哈希的结构中工作。@GrigorAleksanyan,是的,哈希代码可能会发生冲突,
int
可以有2^32个不同的值,这意味着所有字符串都有2^32个哈希代码,但可能的字符串数量是无限的,因此最终可能会发生一些冲突,您无法阻止这种情况。然而,我们的目标是增加唯一性的可能性,而上面的公式(乘以素数)在性能方面做得很好。您如何定义这里的等式
FirstName
LastName
是否完全匹配<代码>姓氏和
姓氏
修剪后是否匹配
FirstName
LastName
在区域设置中匹配