我有一个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?
}
}
答案 0 :(得分: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。
答案 1 :(得分: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。这是不正确的行为。如果你想实现这个行为,那么有一个方法可以完成这个比较,但不是等于。
请参阅http://msdn.microsoft.com/en-us/library/ms173147%28VS.80%29.aspx。
答案 2 :(得分:0)
像亚历克斯所说的那样,这更像是与业务规则相关的事情,我不会为此目的使用Equals。我有另一种方法,它具有Equals方法中的实现。
当然,亚历克斯提到了一个名字+电子邮件的哈希,但是这对你来说也不适用,因为乔恩指出,根据你的业务规则,这不是你能做的事情。
答案 3 :(得分:-4)
有一种方法可以让你做你想做的事。
假设你有一个你定义的枚举
public enum MatchedOn { None, Name, Email }
接下来,将Equals方法的实现拉出到另一个方法中,以便从Equals方法中调用它。在这个新方法中,如果名称相等,则将枚举设置为Name;如果电子邮件相等则将其设置为Email;如果两者都不相同,则设置为None。
然后在您的GetHashCode实现中,您也可以调用此新方法,然后根据名称或电子邮件或两者的组合返回散列代码。
我希望这是有道理的。