Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# Equals 메서드 완벽 이해하기: 참조 동등성과 값 동등성의 차이

C#에서 Equals 메서드는 두 객체가 동일한지 판단할 때 사용됩니다. 별도로 재정의하지 않은 클래스 인스턴스의 경우, Equals는 프로퍼티 값이 아니라 참조(reference)를 비교합니다. 즉, 두 변수가 힙 메모리상의 같은 객체를 가리키고 있는지만 확인합니다.


예를 들어 Employee 클래스의 객체 e와 e2를 만들고, e2 = e처럼 한 객체를 다른 변수에 할당하면 두 변수는 동일한 참조를 공유하게 됩니다. 따라서 Equals 호출 시 예상대로 true가 반환됩니다.


반면 두 번째 경우를 보면, 프로퍼티 값(Name, Age)이 완전히 같음에도 불구하고 Equals가 false를 반환합니다. 이는 인수가 서로 다른 객체를 참조하고 있기 때문입니다. 기본 Equals 구현은 값을 검사하지 않으며, 서로 다른 객체에 대해서는 항상 false를 반환합니다.


예제 1 — 기본 Equals 동작 확인

class Program{
    static void Main(string[] args){
        Employee e = new Employee();
        e.Name = "Test";
        e.Age = 27;
        Employee e2 = new Employee();
        e2 = e;
        var valueEqual = e.Equals(e2);
        Console.WriteLine(valueEqual);
        // 2nd Case
        Employee e1 = new Employee();
        e1.Name = "Test";
        e1.Age = 27;
        var valueEqual1 = e.Equals(e1);
        Console.WriteLine(valueEqual1);
        Console.ReadLine();
    }
}
class Employee{
    public int Age { get; set; }
    public string Name { get; set; }
}

실행 결과

True
False

e.Equals(e2)는 동일한 참조를 가리키므로 true가, e.Equals(e1)은 값이 같아도 별개의 인스턴스이므로 false가 출력됩니다.


예제 2 — Equals와 GetHashCode 오버라이드로 값 비교하기


객체의 내용을 기준으로 동등성을 판단하고 싶다면 Equals 메서드와 GetHashCode 메서드를 직접 오버라이드하면 됩니다. 아래 예제에서는 Age와 Name 프로퍼티가 모두 일치할 때만 true를 반환하도록 재정의했습니다.


class Program{
    static void Main(string[] args){
        Employee e = new Employee();
        e.Name = "Test";
        e.Age = 27;
        Employee e2 = new Employee();
        e2 = e;
        var valueEqual = e.Equals(e2);
        Console.WriteLine(valueEqual);
        Employee e1 = new Employee();
        e1.Name = "Test";
        e1.Age = 27;
        var valueEqual1 = e.Equals(e1);
        Console.WriteLine(valueEqual1);
        Console.ReadLine();
    }
}
class Employee{
    public int Age { get; set; }
    public string Name { get; set; }
    public override bool Equals(object? obj){
        if (obj == null)
            return false;
        if (this.GetType() != obj.GetType()) return false;
        Employee p = (Employee)obj;
        return (this.Age == p.Age) && (this.Name == p.Name);
    }
    public override int GetHashCode(){
        return Age.GetHashCode() ^ Name.GetHashCode();
    }
}

실행 결과

True
True

오버라이드 후에는 두 객체가 서로 다른 인스턴스라도 프로퍼티 값이 같으면 Equals가 true를 반환합니다. 참고로 Equals를 재정의할 때는 반드시 GetHashCode도 함께 재정의해야 합니다. 그렇지 않으면 Dictionary나 HashSet 같은 해시 기반 컬렉션에서 객체가 의도대로 동작하지 않을 수 있습니다.