본문 바로가기
C#

[C#] IComparer<T>, IComparer, Comparer<T>

by DANEW 2023. 10. 4.

IComparer<T> 인터페이스

 

IComparer<T> 인터페이스 (System.Collections.Generic)

형식에서 두 개체를 비교하기 위해 구현하는 메서드를 정의합니다.

learn.microsoft.com

namespace System.Collections.Generic
{
    public interface IComparer<in T>
    {
        int Compare(T x, T y);
    }
}

IComparer 인터페이스

 

IComparer 인터페이스 (System.Collections)

두 개체를 비교하는 메서드를 노출합니다.

learn.microsoft.com

namespace System.Collections
{
    public interface IComparer
    {
        int Compare(object x, object y);
    }
}

Comparer<T> 클래스

 

Comparer<T> 클래스 (System.Collections.Generic)

IComparer<T> 제네릭 인터페이스의 구현에 대한 기본 클래스를 제공합니다.

learn.microsoft.com

namespace System.Collections.Generic
{
    public abstract class Comparer<T> : IComparer, IComparer<T>
    {
        protected Comparer();
 
        public static Comparer<T> Default { get; }
       
        public static Comparer<T> Create(Comparison<T> comparison);
        public abstract int Compare(T x, T y);
    }
}
반응형

- 순서 비교 구현을 위한 순서 비교자를 만드는데 쓰임 
- 정렬된 컬렉션이나 사전에 유용
- Dictionary나 Hashtable같은 비정렬 사전에는 쓸모 없음
- 인터페이스를 직접 구현하는 대신 상속을 통해 순서 비교자를 만드는데 사용되는 추상 클래스 Comparer<T>

List + Comparer 예제

namespace Practice
{
    class Program
    {
        public static void Main(string[] arg)
        {
            var wishList = new List<Wish>();
 
            wishList.Add(new Wish("여행", 2));
            wishList.Add(new Wish("취직", 1));
            wishList.Add(new Wish("결혼", 3));
           
            wishList.Sort(new WishComparer());
 
            foreach (var item in wishList)
            {
                Console.WriteLine($"{item.Priority}: {item.Name}");
            }
        }
    }
 
    class Wish
    {
        public string Name { get; set; }
        public int Priority { get; set; }
 
        public Wish (string name, int priority)
        {
            Name = name;
            Priority = priority;
        }
    }
 
    class WishComparer : Comparer<Wish>
    {
        public override int Compare(Wish x, Wish y)
        {
            // 안전을 위한 점검
            // Equals 메서드와 모순되지 않는 결과를 내기 위해
            // x가 null일수도 있기에 x.Equals보다는 object.Equals를 이용
            if(object.Equals(x, y))
            {
                return 0;
            }
            return x.Priority.CompareTo(y.Priority);
        }
    }
}

SortedDictionary + Comparer 예제

namespace Practice
{
    class Program
    {
        public static void Main(string[] arg)
        {
            var dic = new SortedDictionary<string, int>(new SurnameComparer());
 
            dic.Add("MacPhail", 2);
            dic.Add("MacWilliam", 3);
            dic.Add("McDonald", 1);
 
            foreach (var item in dic)
            {
                Console.WriteLine($"{item.Key}: {item.Value}");
            }
        }
    }
 
    class SurnameComparer : Comparer<string>
    {
        string Normalize (string str)
        {
            str = str.Trim().ToUpper();
 
            if(str.StartsWith ("MC"))
            {
                str = "MAC" + str.Substring(2);
            }
 
            return str;
        }
 
        public override int Compare(string x, string y)
        {
            return Normalize(x).CompareTo(Normalize(y));
        }
    }
}

 

반응형