2010-11-08 5 views
0

У меня есть класс Person, для которого я должен переопределить метод Equals и GetHashCode. Объекты с двумя объектами равны, если имя совпадает с ИЛИ, если совпадает адрес электронной почты. Каков хороший способ сделать это с помощью значительно эффективной хэш-функции?GetHashCode Внедрение Equals для класса в C#

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

Возможный дубликат [Что является лучшим алгоритмом для переопределенного System.Object.GetHashCode?] (Http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden -system-object-gethashcode) – Gonzalo

+1

@Gonzalo: Это абсолютно * не * дубликат этого. Это совсем другая ситуация. –

ответ

10

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

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

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

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

+0

согласился, математическое уравнение неразрешимо, за исключением случаев, когда x = y – TerrorAustralis

+0

@TA. Уравнение не является абсолютно несократимым. * return 1; * подходит для всех необходимых условий работы GetHashCode, просто производительность будет ужасной. – tnyfst

+1

@tnyfst: Следовательно, мой бит «Ну, не иначе, как вернуть постоянное значение». –

8

Я знаю, что это не отвечает на ваш вопрос, но ваш подход неверен. Ожидается, что если a == b и b == c, обязательно следует, что a == c.

Person a: 
    name: mike 
    email: [email protected] 

Person b: 
    name: steve 
    email: [email protected] 

Person c: 
    name: steve 
    email: [email protected] 

В этом примере a == b и b == c, но a! = C. Это неправильное поведение. Если вы хотите реализовать это поведение, отлично иметь метод, который равен Equals, который делает это сравнение, но не равен.

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

+0

Хорошо пятнистый.Не знаю, как я это забыл. –

0

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

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

-4

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

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

public enum MatchedOn { None, Name, Email } 

Далее, вытаскивать реализацию вашего метода Equals в другой такой метод, который вы называете его из вашего метода Equals. В этом новом методе установите для перечисления имя, если имена равны или электронная почта, если электронные письма равны или отсутствуют, если они не совпадают.

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

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

+0

-1: Это не имеет смысла и не будет работать в [примере Джона Скита] (http://stackoverflow.com/questions/4128584/gethashcode-equals-implmentation-for-a-class-in-c/4128616 # 4128616), если «GetHashCode» не может меняться между вызовами, что не должно. – Brian

+0

@Brian. Существует множество правил реализации GetHashCode(). Если вы и ОП действительно хотите знать здесь, то это: 1. Если два объекта равны, как определено оператором ==, они ДОЛЖНЫ генерировать один и тот же хэш-код. 2. GetHashCode() должен быть инвариантным к экземпляру. 3. Функция Hash должна генерировать случайное распределение по диапазону целых чисел. –

+0

Теперь вам не нужно (и не следует) реализовать GetHashcode, если вы не намерены использовать свой тип в качестве ключа в словаре или HashSet. Но, видя, что ОП не упоминает эту потребность и не заботится о других правилах, я не понимаю, почему вы повесили трубку «не должны меняться», когда нет упоминания о том, что его тип клиента является неизменным. –

Смежные вопросы