참조 유형에 대한 Equals()의 "가장 좋은" 정식 구현은 무엇입니까?
문제
참조 유형에 대해 Equals()를 구현하는 것은 생각보다 어렵습니다.현재 정식 구현은 다음과 같습니다.
public bool Equals( MyClass obj )
{
// If both refer to the same reference they are equal.
if( ReferenceEquals( obj, this ) )
return true;
// If the other object is null they are not equal because in C# this cannot be null.
if( ReferenceEquals( obj, null ) )
return false;
// Compare data to evaluate equality
return _data.Equals( obj._data );
}
public override bool Equals( object obj )
{
// If both refer to the same reference they are equal.
if( ReferenceEquals( obj, this ) )
return true;
// If the other object is null or is of a different types the objects are not equal.
if( ReferenceEquals( obj, null ) || obj.GetType() != GetType() )
return false;
// Use type-safe equality comparison
return Equals( (MyClass)obj );
}
public override int GetHashCode()
{
// Use data's hash code as our hashcode
return _data.GetHashCode();
}
나는 이것이 모든 구석구석(상속 등)의 경우를 다루고 있다고 생각하지만 내가 틀렸을 수도 있습니다.여러분은 어떻게 생각하시나요?
해결책
나는 이것에 대해 꽤 포괄적인 가이드를 얼마 전에 썼습니다.시작하려면 동등 구현을 공유해야 합니다(예:객체를 취하는 오버로드는 강력한 형식의 객체를 취하는 오버로드로 전달되어야 합니다.또한 GetHashCode를 재정의해야 하기 때문에 개체가 변경 불가능해야 한다는 등의 사항을 고려해야 합니다.자세한 내용은 여기를 참조하세요:
http://gregbeech.com/blog/implementing-object-equality-in-dotnet
다른 팁
this._data가 참조 유형이기도 하면 null이 아니기를 바라는 것이 좋습니다.
public bool Equals( MyClass obj )
{
if (obj == null) {
return false;
}
else {
return (this._data != null && this._data.Equals( obj._data ))
|| obj._data == null;
}
}
public override bool Equals( object obj )
{
if (obj == null || !(obj is MyClass)) {
return false;
}
else {
return this.Equals( (MyClass)obj );
}
}
public override int GetHashCode() {
return this._data == null ? 0 : this._data.GetHashCode();
}
상속에 관해서는 OO 패러다임이 마법을 발휘하도록 놔두는 것이 좋다고 생각합니다.
구체적으로, GetType()
검사를 제거해야 하며, 이로 인해 다형성이 중단될 수 있습니다.
나는 chakrit에 동의합니다. 서로 다른 유형의 객체가 동일한 데이터나 ID를 갖는 경우 의미상 동일하도록 허용되어야 합니다.
개인적으로 저는 다음을 사용합니다.
public override bool Equals(object obj)
{
var other = obj as MyClass;
if (other == null) return false;
return this.data.Equals(other.data);
}
값 유형을 작성하는지 참조 유형을 작성하는지에 따라 다릅니다.정렬 가능한 값 유형의 경우 다음을 권장합니다.프레임워크 디자인 지침을 준수하는 뼈대 값 유형을 구현하는 Visual Studio 2005용 코드 조각