HaPpY hApPy

9. ReferenceEquals(), static Equals(), instance Equals(), operator== 의상호연관성의 이해 본문

.NET/Effective C#

9. ReferenceEquals(), static Equals(), instance Equals(), operator== 의상호연관성의 이해

juniguya 2014. 3. 16. 12:46

1.    c#에서 두개의 객체가 동일한가 확인하기 위한 4가지 메서드가 존재.

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);

1.      여러개가 존재하는 이유

+ Value 타입과 Reference Type  때문에

- Reference Type 은 같은 주소를 가지고 있어야 동일함

- Value는 같은 주소는 아니라도 같은 값을 가지면 동일함

 

 

2.    재정의 하면 안되는 함수 2

1.     1,2 번째는 절대 재 정의하면안됨.

A.     ReferenceEquals Value, Reference Type에 상관없이 동일한 객체 참조 할 경우 true

 

주의 Boxing에 의한 주소 변환

int i = 5;
if (Object.ReferenceEquals(i, i))
Console.WriteLine("Never happens.");
else
Console.WriteLine("Always happens.");

* 위 결과는 항상 false 인데 이유는 i value type 이기 때문에 boxing 이 된 이후에 비교가 이루어지는데 여기서 boxing이 두번 일어나고 각 각 다른 heap영역 (주소)에 저장되기 때문에 동일한 reference를 참조하지 않음!

 

B.     public static bool Equals() 재정의 하면안됨 이 함수는 내부적으로 정상적으로 instance Equals() operator == 를 사용하기 때문에 사용자가 절대 제 정의 해서는안된다.

   

public static new bool Equals(object left, object right)
{

// Check object identity
if (Object.ReferenceEquals(left, right) )
   return true;

// both null references handled above

if (Object.ReferenceEquals(left, null) || Object.ReferenceEquals(right, null))
    return false;

return left.Equals(right);

}

 

C.      Instance Object.Equals()  

+ Reference Type의 경우 Object.ReferenceEquals()와 완전 동일

하지만 사용자가 재 정의 가능

- e.g. string의 경우 서로 Reference가 달라도 문자열이 동일하면 Equals() true 리턴

 

+ Value Type의 경우 재 정의 해주는게 좋음

-  Value Type경우 공통 상위 타입인 System.ValueType Object 타입의 Instance Equals()를 재정의 함

- 내부적으로 Reflection을 사용하여 수행성능에 영향을 끼침

 전형적인 Instance Object.Equals() override 방법

public class Foo : IEquatable<Foo>

{

public override bool Equals(object right)

{
    // check null:
    // this pointer is never null in C# methods.
    if (object.ReferenceEquals(right, null))
        return false;
    if (object.ReferenceEquals(this, right))
        return true;

 // Foo를 상속받는 클래스로인해 인해 잘못된 비교가 이루어 질수 있기 때문에 this Type을 가지고 비교해야 정확한 비교가 된다.
if (this.GetType() != right.GetType())
    return false;
// Compare this type's contents here:
return this.Equals(right as Foo);\

}

#region IEquatable<Foo> Members

   public bool Equals(Foo other) 
   {
    // elided.
    return true;  

    }   

      #endregion

}

 

D.     4번째 operator == value 타입일 경우는 성능상의 문제로 재 정의 하는것이 좋다.