2010-12-12 2 views
10

작성한 structsclasses에 대한 일치 검사를 작성하는 방법은 무엇입니까?C# 동일성 검사

1)은 검사 "전체"평등은 상용구 코드의 많은이 필요합니까 (같은 override Equals, override GetHashCode 일반 Equals, operator==, operator!=)?

2) 클래스가 IEquatable<T> 인터페이스를 모델로 명시 적으로 지정합니까? 내가 a == b 같은 것을 호출하고 난 항상 Equalsoperator== 회원 모두 구현해야 할 때

3)

, 나는 자동으로 Equals 오버라이드 (override)를 적용하는 실제 방법이 없다는 것을 제대로 이해하고 있는가?

답변

20

을,이 보일러 플레이트 코드를 많이이며, 별도로 모든 것을 구현해야합니다.

나는 것 권장 사항 :

  • 당신이 모든 가치의 평등을 구현하기 위하여려고하는 경우에, GetHashCodeEquals(object)를 오버라이드 (override) - ==에 대한 과부하를 작성하고 있다면
  • 난 항상 IEquatable<T>을 구현하는 것이 매우 예기치 않은 동작이 발생할 수있는 일을하지 않고 IEquatable<T>를 구현 Equals(object)GetHashCode
  • 을 무시 나는 봉인되지 않은 클래스를 올바르게 평등을 구현 == 연산자 드물게
  • 과부하가 까다 롭습니다, 그리고 수는 여전히 놀라운/바람직하지 않은 결과를 생산하고 있습니다. 계층 구조의 유형에 대해 동등해야하는 경우 관심있는 비교를 표현하는 IEqualityComparer<T>을 구현하십시오.
  • 가변 유형에 대한 동일성은 일반적으로 두 가지 객체가 동일 할 수 있고 이후에 동일하지 않을 수 있으므로 나쁜 생각입니다.객체가 해시 테이블에서 키로 사용 된 후에 균등 한 방식으로 변형되면 객체를 다시 찾을 수 없습니다.
  • 보일러 플레이트의 일부는 구조체와 약간 다릅니다 ...하지만 Marc처럼 구조체를 거의 작성하지 않습니다. 여기

는 샘플 구현의 :

using System; 

public sealed class Foo : IEquatable<Foo> 
{ 
    private readonly string name; 
    public string Name { get { return name; } } 

    private readonly int value; 
    public int Value { get { return value; } } 

    public Foo(string name, int value) 
    { 
     this.name = name; 
     this.value = value; 
    } 

    public override bool Equals(object other) 
    { 
     return Equals(other as Foo); 
    } 

    public override int GetHashCode() 
    { 
     int hash = 17; 
     hash = hash * 31 + (name == null ? 0 : name.GetHashCode()); 
     hash = hash * 31 + value; 
     return hash; 
    } 

    public bool Equals(Foo other) 
    { 
     if ((object) other == null) 
     { 
      return false; 
     } 
     return name == other.name && value == other.value; 
    } 

    public static bool operator ==(Foo left, Foo right) 
    { 
     return object.Equals(left, right); 
    } 

    public static bool operator !=(Foo left, Foo right) 
    { 
     return !(left == right); 
    } 
} 

그리고 네, 그 구현 :(

==의 구현은 약간 사이 변화 거의있는, 상용구의 많은의 지옥이다은 동적 유형 검사를 수행해야하는 Equals(object)으로 전화를 걸기 때문에 효율성이 떨어집니다 ...하지만 대체 방법은 다음과 같이 보일러 플레이트가 더 많습니다.

public static bool operator ==(Foo left, Foo right) 
{ 
    if ((object) left == (object) right) 
    { 
     return true; 
    } 

    // "right" being null is covered in left.Equals(right) 
    if ((object) left == null) 
    { 
     return false; 
    } 
    return left.Equals(right); 
} 
+1

^^ 여러분의 각 게시물을 참조 :) C#을 학습 장 .. :) – Dienekes

+0

두 번째 코드 블록에 대한 2 가지 제안 : 1)'== (객체) right'을'=='에서 일반 'Equals'로 이동하지 않아야합니까? 그래서 그것은 속도를 제공합니다 (물론 그것은 달려 있지만 최악의 경우를 가정합니다). 일반적인 Equals 메소드에 대해서도 참조 평등을 검사합니까? 2)'=='에 두 번째 널 체크'(객체) right == null'이 필요 없다는 것은 일반적인'Equals'에서 본질적으로 그러합니다. 내 게시물을보세요 .. – nawfal

+0

@nawfal : 일반적인 '평등'의 경우에 그렇게하는 것이별로 중요하지 않다고 생각합니다. 어쨌든 * 그것이 사실 일 경우에는 빠를 것입니다. * 사실이 아니므로 아무런 유익이 없다는 추가 검사가 추가됩니다. null 부분에 대해서는 동적 유형 검사가 다시 필요합니다. 예, 당신은 둘 다 논쟁 할 수 있습니다.하지만 2 년 전에 제가 쓴 글에서 충분히 행복합니다 ... –

1

a == b에 대해 연산자 ==를 구현하면됩니다.
사전의 데이터가 마음에들 때로는 GetHashCode를 무시합니다.
다음에는 Equals (언급되지 않은 표준 ... 제네릭 사용시 동등성에 대한 제한이 없기 때문에)을 구현하고 IEquatable 구현을 지정합니다. 이 작업을 수행 할 것이므로 저는 == 및! = 구현을 Equals로 지정할 수 있습니다. :)

6

나는 수업을위한 특별한 일을 거의하지 않는다. 대부분의 정규 객체에 대해서는 참조 평등이 잘 작동합니다.

나는 드물게 struct; 그러나 구조체가 값을 나타내므로 등호를 제공하는 것이 일반적으로 적합합니다. 이것은 보통 모든 것을 포함합니다. 이 EqualityComparer<T>.Default을 사용하여 시나리오에서 권투를 피할 수 있기 때문에 (==,! = 같음과 IEquatable<T>.

을 상용구는 일반적으로 너무 문제가 아니라, ReSharper에서 같은 IIRC 도구가 여기에 도움이 될 수 있습니다.

네, 좋습니다 동기화 같음 및 ==를 유지하고,이 명시 적으로 수행해야 할 수 있습니다. 당신 말이 맞아