[C#] IEquatable과 Object.Equals ()를 재정의하는 것의 차이점은 무엇입니까?

내 원하는 Food것이 다른 인스턴스와 동일한 때마다 클래스를 테스트 할 수 있도록 Food. 나중에 List에 대해 사용하고 그 List.Contains()방법 을 사용하고 싶습니다 . 구현 IEquatable<Food>또는 재정의 해야합니까 Object.Equals()? MSDN에서 :

이 메소드는 오브젝트의 IEquatable.Equals 메소드 (목록의 값 유형)에 대한 정의에 정의 된대로 기본 동등 비교기를 사용하여 동등성을 판별합니다.

그래서 다음 질문은 .NET 프레임 워크의 어떤 함수 / 클래스를 사용 Object.Equals()합니까? 처음에 사용해야합니까?



답변

주된 이유는 성능입니다. 제네릭은 .NET 2.0에 도입되었을 때 그들은 같은 깔끔한 클래스의 무리를 추가 할 수 있었다 List<T>, Dictionary<K,V>, HashSet<T>, 등이 구조를 많이 사용 GetHashCode하고 Equals. 그러나 가치 유형의 경우 권투가 필요했습니다. IEquatable<T>구조체가 강력한 형식의 Equals메서드를 구현할 수 있으므로 권투가 필요하지 않습니다. 따라서 일반 컬렉션에 값 유형을 사용할 때 훨씬 더 나은 성능을 제공합니다.

참조 유형은 그다지 도움이되지 않지만 IEquatable<T>구현을 통해 System.Object자주 호출되는 경우 차이를 만들 수 있는 캐스트를 피할 수 있습니다.

Jared Parson의 블로그 에서 언급했듯이 여전히 Object 재정의를 구현해야합니다.


답변

MSDN 에 따르면 :

당신이 구현하는 경우 IEquatable<T>, 당신은 또한의 기본 클래스 구현을 오버라이드 (override)
Object.Equals(Object)하고 GetHashCode
그래서 그들의 행동은 그와 일치하는지 IEquatable<T>.Equals
방법. 당신은 대체를 할 경우
Object.Equals(Object), 재정의 된 구현은 정적에 대한 호출에서 호출되는 Equals(System.Object,
System.Object)
클래스에 방법. 이렇게하면 Equals메소드 의 모든 호출이 일관된 결과를 리턴합니다.

따라서 클래스가 어떻게 사용되는지에 따라 호출 될 수 있다는 점을 제외하고는 둘 사이에 실질적인 기능적 차이가없는 것 같습니다. 성능 관점에서 볼 때 권투 / 언 박싱 페널티가 없기 때문에 일반 버전을 사용하는 것이 좋습니다.

논리적 관점에서 인터페이스를 구현하는 것이 좋습니다. 객체를 재정의한다고해서 클래스가 실제로 동일하다는 사실을 다른 사람에게 알리지는 않습니다. 재정의는 클래스를 수행하지 않거나 얕은 구현 일 수 있습니다. “이것은 평등 검사에 유효합니다!” 더 나은 디자인입니다.


답변

Josh가 말한 내용을 실제 사례로 확장합니다. 조쉬에게 +1-내 대답에 똑같이 쓰려고했다.

public abstract class EntityBase : IEquatable<EntityBase>
{
    public EntityBase() { }

    #region IEquatable<EntityBase> Members

    public bool Equals(EntityBase other)
    {
        //Generic implementation of equality using reflection on derived class instance.
        return true;
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as EntityBase);
    }

    #endregion
}

public class Author : EntityBase
{
    public Author() { }
}

public class Book : EntityBase
{
    public Book() { }
}

이렇게하면 모든 파생 클래스에서 즉시 사용할 수있는 재사용 가능한 Equals () 메서드가 있습니다.


답변

를 호출하면 object.Equals값 유형에 대한 비싼 권투가 발생합니다. 성능에 민감한 시나리오에서는 바람직하지 않습니다. 해결책은 IEquatable<T>입니다.

public interface IEquatable<T>
{
  bool Equals (T other);
}

배후의 아이디어 IEquatable<T>는 결과는 object.Equals같지만 더 빠르다는 것입니다. 구속 조건 where T : IEquatable<T>은 다음과 같은 일반 유형과 함께 사용해야합니다.

public class Test<T> where T : IEquatable<T>
{
  public bool IsEqual (T a, T b)
  {
    return a.Equals (b); // No boxing with generic T
  }
}

그렇지 않으면에 바인딩됩니다 slower object.Equals().


답변