简体   繁体   English

GetHashCode等于C#中的类的实现

[英]GetHashCode Equals implementation for a class in C#

I have a class Person for which I have to override the Equals and GetHashCode method. 我有一个Person类,必须重写Equals和GetHashCode方法。 Two person objects are equals if the Name matches OR if the Email matches. 如果名称匹配或电子邮件匹配,则两个人对象相等。 What's a good way of doing this with a considerably efficient hash function? 用相当有效的哈希函数执行此操作的好方法是什么?

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?
    }
}

You can't, really. 你不能,真的。 Well, not apart from returning a constant value. 好吧,除了返回常量值之外。

Look at it this way... all people with email "x" have to have the same hash code, because they're equal. 这样看吧...所有拥有电子邮件“ x”的人都必须具有相同的哈希码,因为它们是相等的。 And all people with name "y" have to have the same hash code, and so it goes on: 并且所有名称为“ y”的人都必须具有相同的哈希码,因此它继续进行:

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

Note how we've managed to change both the name and the email to arbitrary values, but the hash has to still be h1. 请注意,我们如何设法将名称电子邮件都更改为任意值,但哈希值仍必须为h1。

I know that this does not answer your question, but your approach is incorrect. 我知道这不能回答您的问题,但是您的方法不正确。 It is expected that if a == b, and b == c, it necessarily follows that a == c. 可以预期,如果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

In this example a == b, and b == c, but a != c. 在此示例中,a == b,b == c,但是a!= c。 This is incorrect behavior. 这是不正确的行为。 If you want to implement this behavior, it is perfectly fine to have a method other that Equals that does this comparison, but not equals. 如果要实现此行为,则最好使用Equals以外的方法进行此比较,但不等于。

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

Like Alex said, this is more of a business rule related thing and I wouldn't use Equals for this purpose. 就像Alex所说的,这更多是与业务规则相关的事情,我不会为此目的使用Equals。 I'd have another method that has the implementation you have in the Equals method. 我还有另一种方法可以实现您在Equals方法中的实现。

Of course, Alex mentions a hash of Name+email but that won't work for you either since Jon pointed out, it's not really something you can do given the business rules you have. 当然,Alex提到了Name + email的哈希,但是自从Jon指出以来,这对您都不起作用,考虑到您拥有的业务规则,这实际上不是您可以做的。

There is a way in which you can do what you're trying to do. 有一种方法可以执行您要尝试执行的操作。

Let's say you have an Enum that you've defined like so 假设您有一个这样定义的枚举

public enum MatchedOn { None, Name, Email }

Next, pull out the implementation of your Equals method into another method such that you call it from your Equals method. 接下来,将Equals方法的实现拉到另一个方法中,以便从Equals方法中调用它。 In this new method, set the enum to be Name if the names are equal or Email if the emails are equal or None if neither is the same. 在这种新方法中,如果名称相等,则将枚举设置为Name;如果电子邮件相等,则将枚举设置为Email;如果两者相同,则将None设置为None。

Then in your GetHashCode implementation you can call this new method as well and then return a hashed code based on Name or Email or the combination of both. 然后,在GetHashCode实现中,您也可以调用此新方法,然后基于Name或Email或两者的组合返回哈希码。

I hope that makes sense. 我希望这是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM