2015-06-07 2 views
6
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Crystal_Message 
{ 
    class Person 
    { 
     private string firstName =""; 
     private string lastName= ""; 
     private string phone=""; 


     public Person(string firstName, string lastName, string phone) 
     { 
      this.FirstName = firstName; 
      this.LastName = lastName; 
      this.PhoneNumber = phone; 
     } 

     public string FirstName 
     { 
      get { return firstName; } 

      private set 
      { 
       if (string.IsNullOrWhiteSpace(value)){ 

        throw new ArgumentNullException("Must Include First Name"); 
       } 

       this.firstName = value; 
      } 

     } 

     public string LastName 
     { 
      get { return lastName; } 

      private set 
      { 
       if (string.IsNullOrWhiteSpace(value)){ 

        throw new ArgumentNullException("Must Include Last Name"); 
       } 

       this.lastName = value; 
      } 

     } 

     public string PhoneNumber 
     { 
      get { return phone; } 

      private set 
      { 
       if (string.IsNullOrWhiteSpace(value)){ 

        throw new ArgumentNullException("Must Include Phone Number"); 
       } 

       this.phone = value; 
      } 

     } 


     public override string ToString() 
     { 
      return "First Name: " + this.FirstName + " " + " Last Name: " + this.LastName + " " + " Phone Number: " + this.PhoneNumber; 
     } 

     public override bool Equals(object obj) 
     { 
      if(obj == null) 
      { 
       return false; 
      } 

      Person testEquals = obj as Person; 

      if((System.Object)testEquals == null) 
      { 
       return false; 
      } 

      return (this.firstName == testEquals.firstName) && (this.lastName == testEquals.lastName) && (this.phone == testEquals.phone); 

     } 

     /* 
     public override int GetHashCode() 
     { 
      return 
     } 
     */ 
    } 
} 

Я руководствовался рекомендациями MSDN. Два вопроса:C# Внедрение метода Equals правильно и как реализовать метод GetHashCode

  1. Правильно ли я использовал метод equals?
  2. Может ли кто-нибудь показать мне, как реализовать GetHashCode Правильно для моего класса? MSDN делает x^y, но я не могу сделать это для своего.
+2

Уверенный, что вы можете использовать XOR, использовать его в хеш-коде членов. Вам не нужно, это не обязательно, просто верните phone.GetHashCode(). Это хорошо работает, потому что у каждого есть уникальный номер телефона. –

+0

Спасибо, как насчет метода equals, каких-либо улучшений, или я его правильно реализовал? Это может стать проблемой, потому что два человека могут иметь одинаковое число, жить в одном доме. –

+0

@HansPassant Не у каждого есть уникальный номер телефона. Некоторые люди могут выбрать не вводить свой номер телефона, даже если у них есть, другие могут использовать телефонный номер (корпоративный или семейный телефон). – hvd

ответ

1

Более общий метод, чем простой хэш хэш-кодов, как указано в ответе Филиппа, заключается в использовании более сложной формулы для их комбинирования. Умножьте отдельных полей хэш-коды различных чисел, например так:

public override int GetHashCode() 
{ 
    unchecked 
    { 
     return (firstName.GetHashCode() * 33^lastName.GetHashCode()) * 33^phone.GetHashCode(); 
    } 
} 

(Обратите внимание unchecked ключевое слово:. Целочисленное переполнение, как ожидается, здесь, и молчит оберточного именно предполагаемое поведение)

Это вероятно, не повлияет на конкретные типы, с которыми вы имеете дело, но в целом это лучше. Рассмотрим простой тип, содержащий только два целочисленных значения. Рассмотрим также, что реализация intGetHashCode() просто возвращает свое собственное значение. Если вы используете простой xor для объединения значений, у вас будет много хеш-коллизий для обычного кода: простейшим примером является то, что каждая пара двух одинаковых значений будет генерировать один и тот же хэш-код нуля.

Расчет здесь на самом деле расчет, который делается Tuple<T1, T2, T3>. Я не писал это так, как сделал Microsoft, но фактические вычисления и цифры должны быть одинаковыми.

+0

Спасибо за это. Вы предлагаете мне это делать и для других моих классов? У меня есть класс Employee и класс сообщений. –

+0

@Nexusfactor Я думаю, что до тех пор, пока это упростит проверку правильности вашей реализации 'GetHashCode()', тогда действительно нет причин не делать этого. Но если вы рассматриваете это как дополнительное усложнение, и ваша реализация хеш-кода достаточно хороша, то я, конечно же, пойму, что придерживаюсь собственной реализации хеш-кода. – hvd

+0

Большое спасибо за ваше время и объяснение. Многое присваивается. Просто любопытно, вы узнаете это из учебника/книг? или школа? Хотелось бы узнать больше об этом для моего собственного понимания. –

6

Ну, чтобы не столкнуться с какими-либо проблемами, GetHashCode должен использовать все члены, которые используют Equals, и наоборот.

Так что в вашем случае:

public override int GetHashCode() 
{ 
    return firstName.GetHashCode()^lastName.GetHashCode()^phone.GetHashCode(); 
} 
+0

Я думаю, что это хороший подход. Даже если у двух людей одинаковый номер, первое имя и фамилия разные, чтобы сгенерировать уникальный код HashCode? –

+0

@Nexusfactor да, если по крайней мере одно из ваших полей отличается ... – Filip

+0

Как вы думаете, просто инсус, я должен добавить частный идентификатор int, уникальный идентификатор # для каждого человека? Просто, если есть шанс, что человек из одного дома может иметь одно и то же имя (первый и последний), например, сын может быть назван в честь отца. Однако, оба они должны иметь разные идентификаторы. –

1

Лучший иметь в виду, что цель этих двух методов: С равно вы определить, при каких обстоятельствах два экземпляра вашего класса должны рассматриваться как хорошо, равный , Поэтому, если в вашем случае это указано, если имя, фамилия и номер телефона равны, то это верно. Хэш-метод, в свою очередь, используется для сортировки или распространения экземпляров, например. в хэш-карте. Он должен быть быстрым и достаточно хорошим, чтобы избежать нежелательной кластеризации. Поэтому вы часто видите значения, умноженные на простые в хэш-функциях. Вы должны гарантировать, что одинаковые объекты имеют один и тот же хэш-код, но не наоборот. Таким образом, разные объекты могут иметь один и тот же хэш-код.

+0

«Так что разные объекты могут иметь один и тот же хэш-код» - ну в этом случае вы можете столкнуться с проблемами при использовании HashSet. Потому что он вызовет GetHashCode и предположим, что этот объект уже существует в наборе и не будет его добавлять. Но на самом деле эти объекты не дублируются ... – Filip

+0

См. Https://msdn.microsoft.com/library/system.object.gethashcode%28v=vs.110%29.aspx –

+0

Ссылка ссылается на другой язык. –

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