방프리
22.05.09 Chapter1. 데이터 타입 (Item 9) 본문
Item 9 : 다양한 동일성 개념들 사이의 상관관계를 이해하라
public static bool ReferenceEquals(object left, object right);
public static bool Equals(object left, object right);
public virtual bool Equals(object right);
public static bool operator ==(MyClass left, MyClass right);
객체가 동일한지 비교할 때 위의 함수들을 사용할 수 있고, 각 함수들은 재정의될 수 있다.
또한 IEquatable<T>와 IStructuralEquality를 통해 동일성을 재정의할 수 있다.
하지만 무작정 모든 함수를 재정의해서는 안된다.
위의 정적 함수인 ReferenceEquals는 object 형식의 비교이므로 내부적으로 박싱, 언박싱이 일어난다.
그러기 때문에 이보다 더 정확하게 비교할 수 없으므로 재정의 되서는 안된다.
(하지만 박싱, 언박싱을 하기 때문에 성능상의 이슈가 발생할 수도 있다.)
정적함수 Equals 또한 내부적으로ReferenceEquals와 비슷하게 동작하므로 절대 재정의 되서는 안된다.
Equals() 인스턴스 메서드는 무작정 재정의하는 것이 아닌 기본 동작 방식이 새롭게 작성하는 타입과 어울리지 않을
경우에 재정의한다.
예로 값타입의 경우 객체의 값이 같으면 동일한 객체로 볼 수도 있기 때문이고, 런타임 시 객체의 타입을 사전에
알 수 없기 때문에 리플렉션을 사용하여 성능상 좋지 않다.
Equals()를 구현할 때 되도록 IEquatable<T>를 함께 구현하는 것이 좋다.
public class Foo : IEquatable<Foo>
{
public override bool Equals(object right)
{
if (object.ReferenceEquals(right, null))
return false;
if (object.ReferenceEquals(this, right))
return true;
if (this.GetType() != right.GetType())
return false;
return this.Equals(right as Foo);
}
public bool Equals(Foo other)
{
return true;
}
}
Equals()는 절대 예외를 던져서는 안된다. 그리고 객체의 타입이 동일한지도 반드시 체크해야 한다.
타입 비교를 IEquatable<T>의 구현을 통해 안정성을 보장 받을 수 있다.
Equals를 재정의할 경우 GetHashCode()도 재정의 되어야 한다.
operator ==()는 값 타입을 만들면 재정의하는 것이 좋다. 이유는 Equals() 인스턴스 메서드를 재작성하는 것과
같은 이유이다.
정리하면
1. static Object.ReferenceEquals()와 static Object.Equals() 매서드는 절대 재정의 해서는 안된다.
2. 값 타입의 경우 성능을 개선하기 위해 Equals() 인스턴스 메서드와 operator ==()는 항상 재정의 하는 것이 좋다. 또한 Equals() 함수를 재정의할 때 IEquatable<T>를 함께 구현해주어야 한다.
'C# > More Effective C#' 카테고리의 다른 글
23.01.24 Chapter2. API 설계 (Item 11) (0) | 2023.01.24 |
---|---|
23.01.23 Chapter1. 데이터 타입 (Item 10) (0) | 2023.01.23 |
22.05.08 Chapter1. 데이터 타입 (Item 8) (0) | 2022.05.07 |
22.05.07 Chapter1. 데이터 타입 (Item 7) (0) | 2022.05.07 |
22.03.13 Chapter1. 데이터 타입 (Item 6) (0) | 2022.03.14 |