본문 바로가기
C#

[C#] 순서 비교 (IComparable<T>, IComparable)

by DANEW 2023. 8. 26.

순서 비교

- 상대적 순서를 결정하는데 쓰이는 표준 프로토콜

 * IComparable 인터페이스들 (System.IComparable, System.IComparable<T>) * >, < 연산자

 

IComparable 인터페이스 (System)

값 형식 또는 클래스에서 해당 인스턴스를 정렬 및 순서 지정하기 위해 구현하는 일반화된 형식별 비교 메서드를 정의합니다.

learn.microsoft.com

 

IComparable<T> 인터페이스 (System)

인스턴스를 정렬하는 형식 고유의 비교 메서드를 만들기 위해 값 형식 또는 클래스에서 구현하는 일반화된 비교 메서드를 정의합니다.

learn.microsoft.com

 

IComparable

namespace System
{
    public interface IComparable<in T>
    {
        int CompareTo(T other);
    }
}
namespace System
{
    public interface IComparable
    {
        int CompareTo(object obj);
    }
}

- 두개의 인터페이스는 간은 기능성을 제공

- 값 형식의 경우 형식에 안전한 제네릭 인터페이스가 비제네릭 인터페이스보다 빠름

- 대부분의 기반 형식은 두 인터페이스를 모두 구현함

- 커스텀 형식을 작성 할 때, 이 인터페이스들을 구현하는 경우도 있음

 

- CompareTo

 * a가 b보다 뒤에 와야 하면 a.CompareTo(b)는 양수

 * a가 b와 같은 위치에 와야 하면 a.CompareTo(b)는 0

 * a가 b보다 앞에 와야 하면 a.CompareTo(b)는 음수

 

IComparable 대 Equals

- Equals가 true라면 CompareTo는 0을 돌려줘야 함

 * CompareTo의 첫줄에 if(Equals(other)) return 0; 을 넣어주면 규칙을 위반할 가능성이 사라짐

 

- Equals가 false라면 CompareTo는 어떤 값이라도 돌려줄 수 있음

 

- 상등은 비교보다 더 까다롭게 적용할 수 있지만, 비교는 상등보다 더 까다로울 수 없음

 ex) 대소문자 비교, 문화권에 따른 특수 문자 등

 

>, < 연산자

- 일반적으로 IComparable과 모순되지 않는 결과를 내도록 구현

- 일반적으로 >, < 연산자 구현시 IComparable도 구현

- IComparable 구현시 >, < 연산자를 구현하진 않는다.

 

- >, < 연산자를 구현하는 경우

 * 형식에 고유한 '초과'와 '미만' 개념이 아주 강함

 * 순서 비교를 수행하는 방법 또는 문맥이 단 하나

 * 결과가 문화권에 관계없이 동일

반응형
        // 예제: 음표를 나타내는 구조체
        public struct Note : IComparable, IComparable<Note>, IEquatable<Note>
        {
            int semitonesFromA;
 
            public int SemitonesFromA
            {
                get { return semitonesFromA; }
            }
 
            public Note(int semitonesFromA)
            {
                this.semitonesFromA = semitonesFromA;
            }
 
            // IComparable
            public int CompareTo(object obj)
            {
                // 인자가 Note 타입이 아니라면
                if(!(obj is Note))
                {
                    throw new InvalidOperationException("CompareTo: 음표가 아님!");
                }
                else
                {
                    // 제네릭 IComparable 쪽에서 연산
                    return CompareTo((Note)obj);
                }              
            }
 
            // IComparable<Note>
            public int CompareTo(Note other)
            {
                // 실패의 여지가 없는 점검
                if(Equals(other))
                {
                    return 0;
                }
                else
                {
                    return semitonesFromA.CompareTo(other.semitonesFromA);
                }                
            }
 
            // >, < 연산자
            public static bool operator >(Note n1, Note n2) => n1.CompareTo(n2) > 0;
            public static bool operator <(Note n1, Note n2) => n1.CompareTo(n2) < 0;
 
            /**************************************************************************/
 
            // Equals Custom
            public override bool Equals(object obj)
            {
                if(!(obj is Note))
                {
                    return false;
                }
                else
                {
                    return Equals((Note)obj);
                }
            }
 
            // IEquatable<Note>
            public bool Equals(Note other) => semitonesFromA == other.semitonesFromA;
 
            // GetHashCode Custom
            public override int GetHashCode() => semitonesFromA.GetHashCode();
 
            // ==, != 연산자
            public static bool operator ==(Note n1, Note n2) => n1.Equals(n2);
            public static bool operator !=(Note n1, Note n2) => !(n1 == n2);

 

 

 

반응형

'C#' 카테고리의 다른 글

[C#] AppContext  (1) 2023.08.30
[C#] Process  (1) 2023.08.29
[C#] Environment  (0) 2023.08.28
[C#] Console  (1) 2023.08.27
[C#] 상등 비교 (IEquatable<T>)  (0) 2023.08.25
[C#] Guid  (0) 2023.08.24
[C#] Math  (1) 2023.08.23
[C#] Tuple  (1) 2023.08.22