0Pricing
C# Academy · 강의

비교 연산자 오버로드

==, != 및 순서 비교 연산자를 구현합니다.

비교 연산자 오버로드은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

비교 연산자와 같음

==를 오버로드할 때는 반드시 !=도 오버로드해야 하며, 모든 형태의 같음 비교가 일관되도록 Equals와 GetHashCode도 재정의해야 합니다. C#은 컴파일 시 연산자 쌍을 강제합니다.

== 및 != 오버로드

컴파일러는 ==와 !=를 함께 정의하도록 요구합니다. 두 연산자는 각각 피연산자가 같다고 간주되는지를 나타내는 bool을 반환합니다.

using System;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }

    public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
    public static bool operator !=(Point a, Point b) => !(a == b);

    public override bool Equals(object obj) => obj is Point p && this == p;
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Point(1, 2) == new Point(1, 2));
        Console.WriteLine(new Point(1, 2) != new Point(3, 4));
    }
}

Equals도 항상 재정의하기

연산자는 정적 형식에 따라 컴파일 시 결정되지만, Equals는 가상 메서드이며 컬렉션에서 사용됩니다. 사전과 List.Contains가 ==와 일치하도록 Equals를 재정의하십시오.

using System;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
    public static bool operator !=(Point a, Point b) => !(a == b);
    public override bool Equals(object obj) => obj is Point p && this == p;
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        object a = new Point(1, 2);
        object b = new Point(1, 2);
        Console.WriteLine(a.Equals(b));
    }
}

GetHashCode는 같음과 일치해야 함

두 값이 같다면 동일한 해시 코드를 반환해야 합니다. 그렇지 않으면 Dictionary와 HashSet 같은 해시 기반 컬렉션이 잘못 작동합니다.

using System;
using System.Collections.Generic;

public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
    public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
    public static bool operator !=(Point a, Point b) => !(a == b);
    public override bool Equals(object obj) => obj is Point p && this == p;
    public override int GetHashCode() => HashCode.Combine(X, Y);
}

public class Program
{
    public static void Main()
    {
        var set = new HashSet<Point> { new Point(1, 2) };
        Console.WriteLine(set.Contains(new Point(1, 2)));
    }
}

순서 비교 연산자 < 및 >

관계 연산자도 오버로드할 수 있습니다. 같음 비교와 마찬가지로 <와 >는 함께 정의해야 하며, <=와 >=도 함께 정의해야 합니다.

using System;

public struct Weight
{
    public int Grams;
    public Weight(int g) { Grams = g; }

    public static bool operator <(Weight a, Weight b) => a.Grams < b.Grams;
    public static bool operator >(Weight a, Weight b) => a.Grams > b.Grams;

    public override string ToString() => Grams + "g";
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Weight(100) < new Weight(200));
        Console.WriteLine(new Weight(300) > new Weight(200));
    }
}

참조 형식의 같음

클래스에서 값의 같음은 참조가 아니라 필드를 비교하는 것을 의미합니다. 연산자 내부에서 예외가 발생하지 않도록 null을 신중하게 처리하십시오.

using System;

public class Person
{
    public string Name;
    public Person(string name) { Name = name; }

    public static bool operator ==(Person a, Person b)
    {
        if (ReferenceEquals(a, b)) return true;
        if (a is null || b is null) return false;
        return a.Name == b.Name;
    }
    public static bool operator !=(Person a, Person b) => !(a == b);
    public override bool Equals(object obj) => this == (obj as Person);
    public override int GetHashCode() => Name?.GetHashCode() ?? 0;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Person("Ann") == new Person("Ann"));
    }
}

모든 형태에서 일관성 유지

모든 같음 비교 경로는 일치해야 합니다. 즉 ==, Equals, 해시 코드가 모두 같은 결과를 내야 합니다. 하나의 기준만 유지하도록 Equals를 기준으로 ==를 구현하거나 그 반대로 구현하십시오.

using System;

public struct Id
{
    public int Value;
    public Id(int value) { Value = value; }
    public bool Equals(Id other) => Value == other.Value;
    public override bool Equals(object obj) => obj is Id other && Equals(other);
    public override int GetHashCode() => Value;
    public static bool operator ==(Id a, Id b) => a.Equals(b);
    public static bool operator !=(Id a, Id b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Id(7) == new Id(7));
        Console.WriteLine(new Id(7).Equals(new Id(8)));
    }
}

컬렉션에서 연산자와 Equals 비교

List 검색은 ==가 아니라 Equals를 사용합니다. object 참조를 대상으로 작동하기 때문입니다. ==만 오버로드하고 Equals를 잊으면 검색에서 참조 동일성을 사용하므로 실패할 수 있습니다.

using System;
using System.Collections.Generic;

public struct Tag
{
    public string Name;
    public Tag(string name) { Name = name; }
    public override bool Equals(object obj) => obj is Tag t && t.Name == Name;
    public override int GetHashCode() => Name?.GetHashCode() ?? 0;
    public static bool operator ==(Tag a, Tag b) => a.Equals(b);
    public static bool operator !=(Tag a, Tag b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        var list = new List<Tag> { new Tag("red"), new Tag("blue") };
        Console.WriteLine(list.Contains(new Tag("blue")));
    }
}

컴파일러 경고 올바르게 억제하기

연산자와 함께 Equals 및 GetHashCode를 재정의하는 것은 단순한 예의가 아닙니다. Equals를 재정의하지 않고 ==를 오버로드하면 컴파일러가 경고합니다. 둘 다 구현하면 경고가 사라지고 버그도 방지할 수 있습니다.

using System;

public struct Cell
{
    public int Row, Col;
    public Cell(int r, int c) { Row = r; Col = c; }
    public override bool Equals(object obj) => obj is Cell c && c.Row == Row && c.Col == Col;
    public override int GetHashCode() => HashCode.Combine(Row, Col);
    public static bool operator ==(Cell a, Cell b) => a.Equals(b);
    public static bool operator !=(Cell a, Cell b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new Cell(0, 0) == new Cell(0, 0));
    }
}

모두 함께 적용하기

동등성 비교를 올바르게 지원하는 형식은 ==와 !=를 정의하고, Equals와 GetHashCode를 재정의하며, 모든 비교를 하나의 비교 방식으로 처리합니다. 이는 값 형식의 모범적인 구현입니다.

using System;
using System.Collections.Generic;

public struct Color
{
    public int R, G, B;
    public Color(int r, int g, int b) { R = r; G = g; B = b; }
    public override bool Equals(object obj) => obj is Color c && c.R == R && c.G == G && c.B == B;
    public override int GetHashCode() => HashCode.Combine(R, G, B);
    public static bool operator ==(Color a, Color b) => a.Equals(b);
    public static bool operator !=(Color a, Color b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        var dict = new Dictionary<Color, string> { [new Color(255, 0, 0)] = "red" };
        Console.WriteLine(dict[new Color(255, 0, 0)]);
    }
}

직접 해 보기

같음 비교를 완전히 일관되게 지원하는 구조체를 구현하고, 사전 키로 사용될 때와 == 연산자를 사용할 때 모두 올바르게 작동하는지 확인해 보십시오.

using System;
using System.Collections.Generic;

public struct GridPos
{
    public int Row, Col;
    public GridPos(int r, int c) { Row = r; Col = c; }
    public override bool Equals(object obj) => obj is GridPos p && p.Row == Row && p.Col == Col;
    public override int GetHashCode() => HashCode.Combine(Row, Col);
    public static bool operator ==(GridPos a, GridPos b) => a.Equals(b);
    public static bool operator !=(GridPos a, GridPos b) => !a.Equals(b);
}

public class Program
{
    public static void Main()
    {
        var grid = new Dictionary<GridPos, string> { [new GridPos(1, 1)] = "player" };
        Console.WriteLine(new GridPos(1, 1) == new GridPos(1, 1));
        Console.WriteLine(grid[new GridPos(1, 1)]);
    }
}

빠른 확인

같음 비교 오버로드 규칙을 떠올려 보십시오.

정리

비교 연산자를 오버로드할 때는 일관성이 필요합니다.

  • ==와 !=는 함께 정의해야 하며, </>도 마찬가지입니다.
  • ==와 일치하도록 Equals와 GetHashCode를 재정의하십시오.
  • 같은 값은 동일한 해시 코드를 공유해야 합니다.
  • 결과가 달라지지 않도록 모든 같음 비교를 하나의 비교 메서드로 처리하십시오.

자주 묻는 질문

“비교 연산자 오버로드” 강의는 무료인가요?

네 — “비교 연산자 오버로드” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“비교 연산자 오버로드”에서 뭘 배우나요?

==, != 및 순서 비교 연산자를 구현합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C# Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“비교 연산자 오버로드” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 산술 연산자 오버로드
  2. 비교 연산자 오버로드
  3. 사용자 정의 변환
  4. 연산자 오버로드 모범 사례
← C# Academy(으)로 돌아가기