GetHashCode Равная реализация для класса в C # - PullRequest
0 голосов
/ 09 ноября 2010

У меня есть класс 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 ]

10 голосов
/ 09 ноября 2010

Вы не можете, правда. Ну, не считая возврата постоянного значения.

Посмотрите на это так ... все люди с электронной почтой "х" должны иметь одинаковый хэш-код, потому что они равны. И все люди с именем "y" должны иметь одинаковый хэш-код, и так продолжается:

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

Обратите внимание, что нам удалось изменить как имя , так и адрес электронной почты на произвольные значения, но хэш должен быть h1.

8 голосов
/ 09 ноября 2010

Я знаю, что это не отвечает на ваш вопрос, но ваш подход неверен. Ожидается, что если 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, который выполняет это сравнение, но не равен.

См. http://msdn.microsoft.com/en-us/library/ms173147%28VS.80%29.aspx.

0 голосов
/ 09 ноября 2010

Есть способ, которым вы можете делать то, что пытаетесь сделать.

Допустим, у вас есть Enum, который вы определили так

public enum MatchedOn { None, Name, Email }

Затем извлеките реализацию вашего метода Equals в другой метод, чтобы вы вызывали его из метода Equals. В этом новом методе присвойте enum значение Name, если имена равны, или Email, если адреса электронной почты равны, или None, если они не совпадают.

Затем в вашей реализации GetHashCode вы также можете вызвать этот новый метод и затем вернуть хешированный код на основе имени или адреса электронной почты или их комбинации.

Надеюсь, это имеет смысл.

0 голосов
/ 09 ноября 2010

Как сказал Алекс, это больше относится к бизнес-правилам, и я бы не использовал Equals для этой цели.У меня был бы другой метод, у которого есть реализация, которая есть у вас в методе Equals.

Конечно, Алекс упоминает хэш Name + email, но он также не сработает, так как Джон указал,действительно то, что вы можете сделать, если у вас есть бизнес-правила.

...