C#/.NET(25): == 연산자와 Equals() 메소드
== 연산자는 참조 방식, Equals() 메소드는 오버라이드를 해야 내용을 비교할 수 있다.
참조 타입에서 == 연산자는 참조 방식으로 오브젝트를 비교하지만, Equals 메소드는 오브젝트가 담고 있는 내용을 비교하기 위해 오버라이드 되어야 한다.
만약, 참조 타입에서 Equals 메소드가 오버라이드 되지 않으면, == 연산자처럼 참조 방식으로 오브젝트를 비교하게 된다.
아래는 같은 클래스로 동일한 객체를 생성했을 때, == 연산자와 Equals() 가 어떻게 두 객체를 비교하는지에 대한 예시 코드이다.
using System;
namespace Equal
{
class CustomClass
{
int X;
public CustomClass(int x)
{
X = x;
}
}
internal class Program
{
static void Main(string[] args)
{
var customClass1 = new CustomClass(1);
var customClass2 = new CustomClass(1);
Console.WriteLine($"customClass1 == customClass2: " +
$"{customClass1 == customClass2}"); // false
Console.WriteLine($"customClass1.Equals(customClass2): " +
$"{customClass1.Equals(customClass2)}"); // false
}
}
}
같은 클래스로 동일한 객체를 생성했음에도 두 객체가 다르다는 결과가 나왔다.
이유는 == 연산자와 Equals() 는 참조 비교를 하는데 두 객체가 각각 다른 주소를 갖고 있기 때문에 다르다고 판단하게 된다.
그렇다면, 클래스로 만들어진 오브젝트를 참조 비교가 아닌 내용 비교를 하게 하려면 어떻게 해야할까?
아래 코드와 같이 Equals() 메소드를 내용 비교를 할 수 있도록 오버라이드하면 된다.
(아래 예시 코드에서는 GetHashCode()를 사용하는데, 생략해도 됨. 해당 메소드는 기회가 되면 다루어보겠음.)
using System;
namespace Equal
{
//class CustomClass
//{
// int X;
// public CustomClass(int x)
// {
// X = x;
// }
//}
class CustomClassOverridingEquals
{
int X;
public CustomClassOverridingEquals(int x)
{
X = x;
}
// Equals() 오버라이드
public override bool Equals(object obj)
{
var item = obj as CustomClassOverridingEquals;
if (item == null)
{
return false;
}
return X == item.X;
}
// Equalis() 오버라이드 하기 위해 필요한 메소드
public override int GetHashCode()
{
return X.GetHashCode();
}
}
internal class Program
{
static void Main(string[] args)
{
//var customClass1 = new CustomClass(1);
//var customClass2 = new CustomClass(1);
//Console.WriteLine($"customClass1 == customClass2: " +
// $"{customClass1 == customClass2}"); // false
//Console.WriteLine($"customClass1.Equals(customClass2): " +
// $"{customClass1.Equals(customClass2)}"); // false
var customClass1 = new CustomClassOverridingEquals(1);
var customClass2 = new CustomClassOverridingEquals(1);
Console.WriteLine($"customClass1 == customClass2: " +
$"{customClass1 == customClass2}"); // true
Console.WriteLine($"customClass1.Equals(customClass2): " +
$"{customClass1.Equals(customClass2)}"); // false
}
}
}
그렇다면, Value Type을 == 연산자로 비교하면 어떻게 될까?
Value Type인 struct로 객체를 만들어 == 연산자와 Equal() 로 비교해보겠다.
아래와 같이 struct를 == 연산자로 비교할 수 없음을 알 수 있다.

하지만, Value Type에서 .Equals() 는 오버라이드 없이도 제대로 비교한다는 것을 알 수 있다.
using System;
namespace EqualValueType
{
struct CustomStruct
{
int X;
public CustomStruct(int x)
{
X = x;
}
}
internal class Program
{
static void Main(string[] args)
{
var customStruct1 = new CustomStruct(1);
var customStruct2 = new CustomStruct(1);
//Console.WriteLine($"customStruct1 == customStruct2: " +
// $"{customStruct1 == customStruct2}"); // error
Console.WriteLine($"customStruct1.Equals(customStruct2): " +
$"{customStruct1.Equals(customStruct2)}"); // true
}
}
}
정리: 참조 타입과 값 타입에서 == 연산자와 Equals() 메소드 요약
아래와 같이 정리해보았다.
참조 타입에서 == 연산자와 Equals() 메소드는 둘다 참조 비교하지만, Equals() 메소드를 오버라이드하면 내용 비교를 할 수 있게 된다.
반면에 값 타입에서 참조 비교하는 == 연산자가 그 기능을 제공하지 못한다. 하지만, Eqauls() 메소드는 별도의 오버라이드 없이도 값 타입에서 내용 비교를 할 수 있게 된다.

댓글남기기