0

我有一个 Person 类,我必须为其重写 Equals 和 GetHashCode 方法。如果名称匹配或电子邮件匹配,则两个人对象相等。使用相当有效的哈希函数来做这件事的好方法是什么?

class Person
{
    string Name
    string Email

    public override Equals(object obj)
    {
        if (ReferenceEquals(obj, null))
            return false;
        if (ReferenceEquals(this, obj))
            return true;
        if (obj is Person)
        {
            Person person = (Person)obj;
            return
                (this.Name == person.Name)
                || (this.Email == person.Email);
        }
        return false;
    }

    public override GetHashCode()
    {
        // What's a good way to implement?
    }
}
4

4 回答 4

10

你不能,真的。好吧,除了返回一个常数值。

以这种方式看待...所有使用电子邮件“x”的人都必须具有相同的哈希码,因为他们是平等的。并且所有名称为“y”的人都必须具有相同的哈希码,所以它继续:

Name    Email    Hash
  n1       e1      h1
  n2       e1      h1 (because emails are equal
  n2       e2      h1 (because names are equal to previous)

请注意我们如何设法将名称电子邮件更改为任意值,但哈希值仍必须为 h1。

于 2010-11-08T22:14:19.540 回答
8

我知道这不能回答您的问题,但是您的方法不正确。预计如果a == b,并且b == c,则必然遵循a == c。

Person a:
    name: mike
    email: someone@website.com

Person b:
    name: steve
    email: someone@website.com

Person c:
    name: steve
    email: steve@website.com

在此示例中,a == b,b == c,但 a != c。这是不正确的行为。如果你想实现这个行为,那么有一个 Equals 以外的方法来做这个比较,但不是 equals 是完全可以的。

请参阅http://msdn.microsoft.com/en-us/library/ms173147%28VS.80%29.aspx

于 2010-11-08T22:20:29.693 回答
0

就像亚历克斯所说,这更多是与业务规则相关的事情,我不会为此目的使用 Equals。我有另一种方法,它具有您在 Equals 方法中的实现。

当然,Alex 提到了 Name+email 的哈希值,但这对您也不起作用,因为 Jon 指出,鉴于您拥有的业务规则,这并不是您真正可以做的事情。

于 2010-11-08T22:23:36.900 回答
-4

有一种方法可以让你做你想做的事。

假设您有一个像这样定义的枚举

public enum MatchedOn { None, Name, Email }

接下来,将 Equals 方法的实现提取到另一个方法中,以便从 Equals 方法中调用它。在这个新方法中,如果名称相等,则将枚举设置为 Name;如果电子邮件相等,则将枚举设置为 Email;如果两者都不相同,则将枚举设置为 None。

然后在您的 GetHashCode 实现中,您也可以调用此新方法,然后返回基于 Name 或 Email 或两者组合的哈希代码。

我希望这是有道理的。

于 2010-11-09T07:24:25.810 回答