2009-09-23 4 views
4

이 Person 클래스에 대해 어떻게 생각하십니까? Equals와 GetHashCode를 재정의하는 것이 나쁜 생각입니까 아니면 모범 사례입니까?같음 및 GetHashCode

public class Person { 
    public int PersonId { get; set; } 
    public string Name { get; set; } 
    public override bool Equals(object obj) { 
     var person = obj as Person; 

     return PersonId == person.PersonId; 
    } 
    public override int GetHashCode() { 
     return PersonId; 
    } 

} 

사용법 :

static void Main(string[] args) {   

      var list = new List<Person>(); 
      list.Add(new Person(){ PersonId = 1, Name = "Mike"}); 
      list.Add(new Person() { PersonId = 2, Name = "Michael Sync" }); 
      list.Add(new Person(){ PersonId = 1, Name = "Mike"}); 

      var list1 = new List<Person>(); 
      list1.Add(new Person() { PersonId = 1, Name = "Mike" }); 
      list1.Add(new Person() { PersonId = 3, Name = "Julia" }); 

      var except = list.Except(list1); 

      foreach (var item in except) { 
       Console.WriteLine(item.Name); 
      } 
      Console.ReadKey(); 

     } 

답변

4

몇 가지 포인트 :

  1. 그것은 "다른 종류의"안전 안전 또는 null이 아니다. 이 시도 :

    new Person().Equals(new Object()); 
    

    또는

    new Person().Equals(null); 
    

    방을.

  2. 평등 연산을 정의하는 클래스는 이어야하며 일반적으로은 IMO가되어야합니다. 예를 들어, 오브젝트를 사전 키로 사용한 후에 내용을 변경하는 것은 잘못입니다.

  3. 당신이 ID에 전적으로을 기반 평등을 원하는 여전히 가정 IEquatable<Person>

빠른 재 구현을 구현하는 것이 좋습니다. 내가 볼 수

public sealed class Person : IEquatable<Person> { 

    private readonly int personId; 
    public int PersonId { get { return personId; } 

    private readonly string name; 
    public string Name { get { return name; } } 

    public Person(int personId, string name) { 
     // Is a null name valid? If not, throw here. 
     this.personId = personId; 
     this.name = name; 
    } 

    public override bool Equals(object obj) { 
     return Equals(obj as Person); 
    } 

    public Equals(Person other) { 
     return other != null && other.personId == personId; 
    } 

    public override int GetHashCode() { 
     return personId; 
    } 
} 
+1

+1 불변성에 대한 좋은 지적. –

+2

GetHashCode는 기본적으로 Jon Skeet 박쥐 신호입니까? –

+0

그래서 대부분의 UI 엔티티는 IEquatable로 구현해야합니다. 제안 해 주셔서 감사드립니다. –

0

하나의 문제는 새로운 (저장되지 않은) 레코드 (제로 많이)에 대한 충돌을 많이받을거야 - 당신은 사람들을위한 연속 - 제가 ID를 가지고있는 것처럼 뭔가를 할 ...하지만하지 않는 한 너 정말은 열쇠로 Person을 사용해야합니까? 개인적으로 나는 성가 시게 될 것이라고 생각하지 않습니다 ...

+0

사실 LINQ Except 또는 다른 기능을 사용하고 싶습니다. 현재 우리는 코드를 제외하고 아무것도 사용할 수 없도록 아무 것도 재정의하지 않습니다. 따라서 Entity 클래스에서 무언가를 구현하는 가장 좋은 방법을 찾고 있습니다. –

+0

* 선택기를 사용하여 문제를 더 잘 해결하고 기존 속성 (예 : ID)을 직접 비교할 수있는 시간은 대부분 –

4

예. 잘못되었습니다. 절대은 GetHashCode에 대한 계산의 일부로 변경할 수있는 속성을 사용해야합니다. 그렇게하면 버그를 추적하기 위해 열심히 열 수 있습니다.

+0

입니다. 현재로서는 UI 엔터티 클래스가 해당 속성을 재정의하지 않지만 Except 등을 사용하는 경우에는 제안을 위해 노력하고 있습니다. –