ITEM #9 ReferenceEquals(), static Equals(), instance Equals(), operator==의 상호 연관성을 이해하라
- Posted at 2008/12/01 18:02
- Filed under Enhance your ability(IT)/C#
public static bool 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)
개발에 있어 동일성의 의미를 규정하기 위해서 4개의 메서드 사용할 수 있다.
위 4개의 메서드는 상호 연관되어 있기 때문에 만일 이 중 하나를 재정의하게 되면 다른 메서드의 동작에도 영향을 주게된다.
일단 어떤 상호 연관성이 있는지 부터 알아 보도록 하자.
전제사항,
value 타입의 동일성 비교: 서로 타입이 같고 동일한 값을 가지고 있을경우에 서로 같다고 말한다
reference 타입의 동일성 비교: 동일 객체를 참고 하는 있는 경우 서로 같다고 말한다.
1) ReferenceEquals(): 두개의 변수가 단일 객체를 참조하는 동일한 객체 참조자를 담고 있는 경우 ture를 반환함(이 메세드는 객체의 참조자를 비교한느 역할을 이미 정확히 구현하고 있기 때문에 절대로 재정의 해서도 안되고 할 필요도 없다.)
2) static Object.Equals(): 런타임시에 타입을 정확히 알지 못하는 변수들 간에 비교를 수행하기 위해서 사용된다.
실제 구현부를 살펴 보다면,
public static bool Equals(object left, object right)
{
if(left == right)
return true;
if((left == null) || right == null))
return false;
return left.Equals(right);
}
위의 코드는 == operator와 Instance Equals 로써 동일성 확인을 하게 된다.
만약 사용자가 == operator와 Instance Equals를 override한다면 위 코드는 다른 기능을 작동 할 수 있을 것이다. 이게 서로간의 상관관계가 존재 한다는 것이다.
그럼 == operator와 Instance Equals에 대해 알아 보자
3) instance Obejct.Equals(): 기본적인 Object.Equals()의 동작이 적절하지 않을 경우 재정의를 수행해야 한다.
reference/value 타입의 인스턴스 형 Object.Equals 동작 방식은 서로 다르다.
- Reference 타입의 인스턴스형 Object.Equals(): 기본동작은 Object.ReferenceEquals()와
완전히 동일하다. 만약 변경하고자 한다면 아래 사항을 지키도록 하자
참조자에 대한 단순비교가 아닌 실제 객체가 담고있는 내용을 기반으로 동일성 여부를 판단할
수 있도록 인스턴스형 Equals() 메서드를 재정의 하자.(닷넷프레임워크 클래스 라이브러리의
규칙): operator== 재정의 필요없음
- value 타입의 인스턴스형 Object.Equals(): 모든 value 타입의 공통 상위 타입인
System.ValueType이 Object 타입의 인스턴스형 Equals()의 기본 동작을 재정의하고 있음
허나 value 타입일 경우는 모든 상황을 다 받아 들일수 있게 코드가 작성되어 있기에
(reflection을 사용: 이는 성능상 않좋은 영향을 끼친다)
새로운 value 타입을 만들 때에는 항시 ValueType.Equals()의 구현부를 대체할 수 있는
인스턴스형 Equals()를 재작성하자. 그리고 operator== 재정의 해야한다.
1: null값인지 확인
2: ReferenceEquals() 확인: 동일 객체 참조자 확인
3: GetType() 확인: 정확한 타입을 지정해야 함(this 사용)
4: 내용 비교: 두번째 객체의 형변환 여부확인(A=B와 같다면 B=A도 같아야 함):상속문제
5: 절대 예외는 발생되어서는 안된다.
6: 상위 클래스 즉, System.Object나 System.ValyeType에서 정의한 Equals() 메서드가 호출
되지 않을 것이 확실할 경우에만 시반 클래스의 Equals()를 호출해야 한다는 것이다.
[규칙 정리]
value 타입을 만들 때는 항상 인스턴스형 Equals()를 재정의하고, Reference타입을 만들 때는
System.Object에 정의되어 있는 Equals의 동작방식을 따르고 싶지 않을 경우에 한해서만 위
의 규칙을 사용하여 재정의를 수행 해야 한다. 추가적으로 GetHashCode(0라는 메서드도 같
이 규현 해야한다.(추후 참고)
4) operator==(): value 타입의 비교 일경우만 재정의 해 준다.
결론: C#언어는 4가지의 비교연산 방법을 제공한다.
하지만 이 중 자체적으로 비교 연산을 재정의해야 하는 메서드는 2가지 뿐이다.
타입을 모르는 객체의 동일성 비교시:
static Object.ReferenceEquals()와 static Object.Equals()는 런타임에 피연산자의 타입을 몰라도 제대로 비교연산을 수행할 수 있도록 잘 정의되어 있다.
value 타입을 정의하고 이의 동일성을 비교 할 시:
인스턴스 Equals()와 Operator==을 재 정의하자.
Reference 타입을 정의하고 이의 동일성을 비교 할 시:
객체에 대한 참조자를 비교하는 System. Object의 기본동작을 변경해야 할 경우에 한해서
인스턴스형 Equals()만 정의하자.
public static bool Equals(object left, object right)
public virtual bool Equals(object right)
public static bool operator==(Myclass left, Myclass right)
개발에 있어 동일성의 의미를 규정하기 위해서 4개의 메서드 사용할 수 있다.
위 4개의 메서드는 상호 연관되어 있기 때문에 만일 이 중 하나를 재정의하게 되면 다른 메서드의 동작에도 영향을 주게된다.
일단 어떤 상호 연관성이 있는지 부터 알아 보도록 하자.
전제사항,
value 타입의 동일성 비교: 서로 타입이 같고 동일한 값을 가지고 있을경우에 서로 같다고 말한다
reference 타입의 동일성 비교: 동일 객체를 참고 하는 있는 경우 서로 같다고 말한다.
1) ReferenceEquals(): 두개의 변수가 단일 객체를 참조하는 동일한 객체 참조자를 담고 있는 경우 ture를 반환함(이 메세드는 객체의 참조자를 비교한느 역할을 이미 정확히 구현하고 있기 때문에 절대로 재정의 해서도 안되고 할 필요도 없다.)
2) static Object.Equals(): 런타임시에 타입을 정확히 알지 못하는 변수들 간에 비교를 수행하기 위해서 사용된다.
실제 구현부를 살펴 보다면,
public static bool Equals(object left, object right)
{
if(left == right)
return true;
if((left == null) || right == null))
return false;
return left.Equals(right);
}
위의 코드는 == operator와 Instance Equals 로써 동일성 확인을 하게 된다.
만약 사용자가 == operator와 Instance Equals를 override한다면 위 코드는 다른 기능을 작동 할 수 있을 것이다. 이게 서로간의 상관관계가 존재 한다는 것이다.
그럼 == operator와 Instance Equals에 대해 알아 보자
3) instance Obejct.Equals(): 기본적인 Object.Equals()의 동작이 적절하지 않을 경우 재정의를 수행해야 한다.
reference/value 타입의 인스턴스 형 Object.Equals 동작 방식은 서로 다르다.
- Reference 타입의 인스턴스형 Object.Equals(): 기본동작은 Object.ReferenceEquals()와
완전히 동일하다. 만약 변경하고자 한다면 아래 사항을 지키도록 하자
참조자에 대한 단순비교가 아닌 실제 객체가 담고있는 내용을 기반으로 동일성 여부를 판단할
수 있도록 인스턴스형 Equals() 메서드를 재정의 하자.(닷넷프레임워크 클래스 라이브러리의
규칙): operator== 재정의 필요없음
- value 타입의 인스턴스형 Object.Equals(): 모든 value 타입의 공통 상위 타입인
System.ValueType이 Object 타입의 인스턴스형 Equals()의 기본 동작을 재정의하고 있음
허나 value 타입일 경우는 모든 상황을 다 받아 들일수 있게 코드가 작성되어 있기에
(reflection을 사용: 이는 성능상 않좋은 영향을 끼친다)
새로운 value 타입을 만들 때에는 항시 ValueType.Equals()의 구현부를 대체할 수 있는
인스턴스형 Equals()를 재작성하자. 그리고 operator== 재정의 해야한다.
1: null값인지 확인
2: ReferenceEquals() 확인: 동일 객체 참조자 확인
3: GetType() 확인: 정확한 타입을 지정해야 함(this 사용)
4: 내용 비교: 두번째 객체의 형변환 여부확인(A=B와 같다면 B=A도 같아야 함):상속문제
5: 절대 예외는 발생되어서는 안된다.
6: 상위 클래스 즉, System.Object나 System.ValyeType에서 정의한 Equals() 메서드가 호출
되지 않을 것이 확실할 경우에만 시반 클래스의 Equals()를 호출해야 한다는 것이다.
[규칙 정리]
value 타입을 만들 때는 항상 인스턴스형 Equals()를 재정의하고, Reference타입을 만들 때는
System.Object에 정의되어 있는 Equals의 동작방식을 따르고 싶지 않을 경우에 한해서만 위
의 규칙을 사용하여 재정의를 수행 해야 한다. 추가적으로 GetHashCode(0라는 메서드도 같
이 규현 해야한다.(추후 참고)
4) operator==(): value 타입의 비교 일경우만 재정의 해 준다.
결론: C#언어는 4가지의 비교연산 방법을 제공한다.
하지만 이 중 자체적으로 비교 연산을 재정의해야 하는 메서드는 2가지 뿐이다.
타입을 모르는 객체의 동일성 비교시:
static Object.ReferenceEquals()와 static Object.Equals()는 런타임에 피연산자의 타입을 몰라도 제대로 비교연산을 수행할 수 있도록 잘 정의되어 있다.
value 타입을 정의하고 이의 동일성을 비교 할 시:
인스턴스 Equals()와 Operator==을 재 정의하자.
Reference 타입을 정의하고 이의 동일성을 비교 할 시:
객체에 대한 참조자를 비교하는 System. Object의 기본동작을 변경해야 할 경우에 한해서
인스턴스형 Equals()만 정의하자.
Posted by jongkok4
- Tag
- Effective c#, Equals, operator==, ReferenceEquals
- Response
- 1 Trackback , No Comment
Trackback URL : http://jongkok4.net/trackback/140
Trackbacks List
-
item 9, ReferenceEquals(), static Equals(), instance Equals(), operator==의 상호 연관성을 이해해라.
Tracked from 최익필의 이름없는 블로그 2010/06/26 22:04 RemovePurpose-built post 공부하려고 정리한다. Content 관련 링크 http://blog.naver.com/mrlongpark/150051350956 http://www.jongkok4.net/140 주의 제목에서 ReferenceEquals() 와 static Equals()는 System.Object 객체의 static 멤버 함수이
