Favicon

Equality operators

Peponi11/14/20245m

C#
SyntaxOperator==!=

1. Introduction

==, != 연산자는 피연산자가 같은지 여부를 확인한다.

== 연산자는 피연산자가 같으면 true, 다르면 false를 반환하며 != 연산자는 == 연산자의 반대 결과를 반환한다.

2. 값 형식

int X = 1;
int Y = 2;
int Z = 3;
 
Console.WriteLine(X == Y);
Console.WriteLine(X != Z);
Console.WriteLine(X + Y == Z);
 
/* output:
False
True
True
*/

struct 형식의 경우 기본적으로 같음 연산자를 지원하지 않는다. 같음 연산자를 사용하려면 형식에 해당 연산자를 오버로드해야 한다.

public struct StructTest
{
    public int X;
 
    public static bool operator ==(StructTest left, StructTest right)
    {
        return left.X == right.X;
    }
    public static bool operator !=(StructTest left, StructTest right)
    {
        return left.X != right.X;
    }
}
 
StructTest a = new StructTest();
StructTest b = new StructTest();
a.X = 10;
b.X = 20;
 
Console.WriteLine(a == b);
Console.WriteLine(a != b);
 
/* output:
False
True
*/

3. 참조 형식

참조 형식은 기본적으로 참조 주소를 비교한다.

public class TestClass
{
    public int X;
 
    public TestClass(int x) => X = x;
}
 
var a = new TestClass(5);
var b = new TestClass(5);
var c = b;
 
Console.WriteLine(a == b);
Console.WriteLine(b == c);
 
/* output:
False
True
*/

3.1. Class

class의 경우 struct와 마찬가지로 같음 연산자를 오버로드할 수 있다. 같음 연산자를 오버로드 한 후 참조 주소를 비교하려는 경우, Object.ReferenceEquals() 메서드를 사용하여 비교할 수 있다.

public class TestClass
{
    public int X;
 
    public TestClass(int x) => X = x;
 
    public static bool operator ==(TestClass left, TestClass right)
    {
        return left.X == right.X;
    }
 
    public static bool operator !=(TestClass left, TestClass right)
    {
        return left.X != right.X;
    }
}
 
var a = new TestClass(5);
var b = new TestClass(5);
var c = b;
 
Console.WriteLine(a == b);
Console.WriteLine(b == c);
Console.WriteLine(object.ReferenceEquals(a, b));
Console.WriteLine(object.ReferenceEquals(b, c));
 
/* output:
True
True
False
True
*/

3.2. Record

record 형식의 경우 기본적으로 값 비교를 지원하여 값 및 참조 형식의 비교가 가능하다.

public record Coordinate(int X, int Y);
public record CoordinateCollection(int ID, List<Coordinate> Coordinates);
 
var a = new Coordinate(1, 2);
var b = new Coordinate(2, 3);
var c = new Coordinate(2, 3);
 
Console.WriteLine(a == b);
Console.WriteLine(b == c);
 
var d = new CoordinateCollection(1, new() { new(1,2) });
var e = new CoordinateCollection(1, new() { new(1,2) });
 
Console.WriteLine(d == e);
 
/* output:
False
True
False
*/

record 형식의 경우 같음 연산자를 오버로드 할 수 없다. 기능이 필요한 경우 IEquatable<T>를 구현해야 한다.

public record Coordinate(int X, int Y) : IEquatable<Coordinate>
{
    public virtual bool Equals(Coordinate? other)
    {
        return other is not null && (X == other.X || Y == other.Y);
    }
}
 
var a = new Coordinate(1, 3);
var b = new Coordinate(2, 1);
var c = new Coordinate(2, 3);
 
Console.WriteLine(a == b);
Console.WriteLine(b == c);
Console.WriteLine(a == c);
 
/* output:
False
True
True
*/

3.3. String

string의 경우 참조 형식이지만 값 형식처럼 비교할 수 있다. 두 문자열이 같은 길이 및 문자를 가질 때 true를 반환한다.

string a = "ABCde";
string b = "abcDE";
 
Console.WriteLine(a == b);
Console.WriteLine(a.ToLower() == b.ToLower());
 
/* output:
False
True
*/

3.4. Delegate

delegate의 경우 호출 길이가 같고 동일한 호출 순서를 가질 때 동일하다.

Action action1 = () => Console.WriteLine();
Action action2 = () => Console.WriteLine();
 
Action a = action1 + action2;
Action b = action1 + action2;
Action c = action2 + action1;
 
Console.WriteLine(a == b);
Console.WriteLine(b == c);
Console.WriteLine(object.ReferenceEquals(a, b));
 
/* output:
True
False
False
*/

4. 참조 자료