2013-05-26 6 views
1

는 I 클래스를 가지고 EqualsGetHashCode 방법 재정의 된 두 필드 Foo :LINQ와 EqualityComparer가 다르다 <T>. 기본 : IEquatable <T> 구현이 무시 되었습니까?

public class Foo 
{ 
    private readonly int _x; 
    private readonly int _y; 

    public Foo(int x, int y) { _x = x; _y = y; } 

    public override bool Equals(object obj) { 
     Foo other = obj as Foo; 
     return other != null && _y == other._y; 
    } 

    public override int GetHashCode() { return _y; } 
} 

제가 Foo 배열 만들 경우들과이 어레이의 Distinct 값의 개수 카운트 :

var array = new[] { new Foo(1, 1), new Foo(1, 2), new Foo(2, 2), new Foo(3, 2) }; 
Console.WriteLine(array.Distinct().Count()); 

고유 값의 번호로서 인식된다 :

2 
,451,515,

지금 내 수업 Foo 다음 구현을 사용 IEquatable<Foo>을 구현 한 경우 :

public bool Equals(Foo other) { return _y == other._y; } 

는 고유 값의 수는 여전히 :

:

2 

하지만 이에 대한 구현을 변경하는 경우

public bool Equals(Foo other) { return _x == other._x; } 

계산 된 고유 번호 Foo : s는 3이 아닙니다 (즉, 별개의 _x)도 2 별개의 _y의 (수) 수 있지만 :

4 

그리고 나는 EqualsGetHashCode 재 지정을 주석하지만 IEquatable<Foo> 구현을 유지하는 경우, 대답도 4입니다. MSDN documentation에 따르면

Distinct 과부하는 동등 비교를 정의하는 정적 속성 EqualityComparer.Default를 사용한다 :

The Default property checks whether type T implements the System.IEquatable<T> 
interface and, if so, returns an EqualityComparer<T> that uses that 
implementation. Otherwise, it returns an EqualityComparer<T> that uses the 
overrides of Object.Equals and Object.GetHashCode provided by T. 

그러나 위의 실험을보고,이 사항이 보유하지 않는 것 같습니다. 기껏해야 IEquatable<Foo> 구현은 이미 제공된 EqualsGetHashCode 재정의를 지원하며 최악의 경우 동일성 비교를 완전히 손상시킵니다.

내 질문 :

  • 이유는 무엇입니까 IEquatable<T> 손상 동등 비교의 독립적 인 구현?
  • EqualsGetHashCode 오버라이드와 관계없이 역할을 수행 할 수 있습니까?
  • 그렇지 않은 경우 EqualityComparer<T>.Default은 먼저이 구현을 찾으십니까?

답변

4

귀하의 GetHashCode 방법 y에 따라 달라집니다. 즉, Equals 방법 에 속하지 않는 경우 y에 의존하면 평등성 계약이 파손되었습니다. 일치하지 않습니다.

Distinct() 같은 요소에는 동일한 해시 코드가 있어야합니다. 귀하의 경우, x 값으로 유일한 요소는 다른 해시 코드를 가지고 있으므로 Equals도 호출되지 않습니다. IEquatable<T>.Equals의 문서에서

: 당신이 Equals을 구현하는 경우

, 당신은 또한 Object.Equals(Object)GetHashCode의 기본 클래스 구현을 오버라이드 (override) 할 필요가 그래서 그들의 행동은 IEquatable<T>.Equals 방법과 일관성이다.

Equals(Foo)의 구현은 중 하나Equals(object)또는GetHashCode과 일치하지 않습니다.

EqualityComparer<T>.DefaultGetHashCode 방법으로 위임합니다. Equals(object) 방법보다 우선하여 Equals(T) 방법을 사용합니다.

그래서 위해 귀하의 질문에 대답 :

  • 이유는 무엇입니까 IEquatable<T> 손상 동등 비교의 독립적 인 구현?

일관성없는 구현이 도입 되었기 때문에. 행동 측면에서 보면 을 의미하지 않습니다. 이것은 형식 검사 (및 값 형식의 경우 boxing)를 피함으로써보다 효율적으로 작동하기위한 것입니다.

  • IT는 EqualsGetHashCode 재정의 독립적 인 역할을 할 수 있습니까?

그것은 정신을 위해서 Equals(object)과 일치해야합니다, 그것은 정확성을 위해서 GetHashCode과 일치해야합니다.

그렇지 않은 경우 EqualityComparer<T>.Default은 먼저이 구현을 찾으십니까?

주로 런타임 유형 확인 및 boxing/unboxing을 피하십시오.

+0

많은 감사, 존, 매우 유익한 답변. 나는'IEquatable . Equals' 문서를 더 철저히 읽어야한다는 것을 알고 있습니다. 타입 검사에 대한 좋은 지적은 이것이 현재의 주된 장점이라고 생각합니다 :-) –