IComparable <T> Vs를 사용하는 경우 IComparer <T>


답변:


96

그럼 그들이하지 과 같은 일 IComparer<T>동안 두 개의 서로 다른 객체를 비교 할 수있는 유형에 구현되는 IComparable<T>같은 유형의 다른 인스턴스와 자신을 비교할 수있는 유형에 구현된다.

나는 IComparable<T>다른 인스턴스가 인스턴스와 어떤 관련이 있는지 알아야 할 때 사용하는 경향이 있습니다 this. 비교 IComparer<T>대상이 아니므로 컬렉션을 정렬하는 데 유용합니다 IComparer<T>.


9
IComparer <T>를 사용하면 원하는 각 유형에 대한 클래스를 가질 수도 있습니다. 예; PersonLastFirstNameComparer, PersonFirstLastNameComparer 또는 PersonAgeComparer.
Eric Schneider

쉽게 기억할 수있는 방법이 있습니까? 나는 매번 그것을 찾아야하는 경향이있다.
amadib

59
생각 @amadib IComparable내가 비교 해요 . 그것은 내가 다른 것과 비교할 수 있다는 것을 의미합니다. 그리고 내가 비교 자IComparer 로서 읽었을 때 , 나는 단순히 비교 한다는 의미입니다.
nawfal

@newfal 대답으로 넣어야합니다. 여기서 가장 좋은 설명이라고 생각합니다.
Gene S

42

IComparable<T>클래스에 내재적 비교가있을 때 사용 합니다.

IComparer<T>클래스의 고유 비교 (있는 경우) 이외의 비교 방법을 원할 때 사용 합니다.


28

엔티티에 따라 다릅니다. 예를 들어 "Student"와 같은 클래스의 경우 이름을 기반으로 IComparable을 사용하는 것이 좋습니다.

class Student : IComparable 
{
    public string Name { get; set; }
    public int MathScore { get; set; }
    public int EnglishScore { get; set; }

    public int TotalScore 
    {
        get
        {
            return this.MathScore + this.EnglishScore; 
        }
    }

    public int CompareTo(object obj)
    {
        return CompareTo(obj as Student);  
    }

    public int CompareTo(Student other)
    {
        if (other == null)
        {
            return 1;
        }
        return this.Name.CompareTo(other.Name);  
    }
}

그런데 'A'선생님이 MathScore를 기준으로 학생들을 비교하고 싶다면 'B'선생님이 EnglishScore를 기준으로 학생들을 비교하고 싶어합니다. IComparer를 별도로 구현하는 것이 좋습니다. (전략 패턴과 비슷 함)

class CompareByMathScore : IComparer<Student>
{
    public int Compare(Student x, Student y)
    {
        if (x.MathScore > y.MathScore)
          return 1;
        if (x.MathScore < y.MathScore)
          return -1;
        else
          return 0;
    }
}

사용하기 쉽 도록 Compare 메서드를 정적으로 만듭니다 .

9

그것은 모두 당신의 유형이 변경 가능한지 여부에 달려 있습니다. 변경 불가능한 유형 에서만 IComparable을 구현 해야 합니다 . IComparable을 구현하는 경우 ==,! =, <및> 연산자와 함께 Equals를 재정의해야합니다 (코드 분석 경고 CA1036 참조).

이 블로그 게시물 에서 Dave G를 인용합니다 .

그러나 정답은 개체가 변경 가능한 경우 IComparable 대신 IComparer를 구현하고 필요한 경우 IComparer의 인스턴스를 정렬 함수에 전달하는 것입니다.

IComparer는 해당 시점에서 정렬하는 데 사용되는 일회용 개체 일 뿐이므로 개체는 원하는 변경 가능한 의미를 가질 수 있습니다. 또한 Equals, GetHashCode 또는 == 사용을 요구하거나 제안하지도 않습니다. 원하는 방식으로 자유롭게 정의 할 수 있습니다.

마지막으로 다른 필드 또는 다른 규칙으로 정렬하기 위해 유형에 대해 여러 IComparer를 정의 할 수 있습니다. 이것은 하나의 정의에 집착하는 것보다 훨씬 더 유연합니다.

간단히 말해 , 값 유형에는 IComparable을 사용하고 참조 유형에는 IComparer를 사용하십시오.


6

이야기를 통한 간단한 설명

고등학교 농구. 팀을위한 학교 운동장 선택입니다. 우리 팀에서 가장 키가 크고 / 최고 / 가장 빠른 사람들을 얻고 싶습니다. 어떡하죠?

IComparer 인터페이스 -두 사람을 개별적으로 비교

  • 이렇게하면 정렬 된 두 사람을 비교할 수 있습니다 ....... 기본적으로 그게 다입니다. Fred vs John .......... 인터페이스를 구현하는 구체적인 클래스에 그들을 던졌습니다. Compare(Fred, John)누가 더 나은지 뱉어냅니다.

IComparable은 어떻습니까? -다른 사람과 자신을 비교

최근에 FB에 가본 적이 있습니까? 다른 사람들이 멋진 일을하는 것을 볼 수 있습니다. 세계를 여행하고, 발명품을 만들고, 제가 그다지 멋지지 않은 일을하고 있습니다. 우리가하는 일은 IComparable 인터페이스를 사용하는 것입니다.

  • 현재 인스턴스 (자신)를 동일한 유형 (사람)의 다른 개체 (다른 사람)와 비교하고 있습니다.

비교 자 클래스는 어떻습니까?

Comparer 클래스는 IComparer 인터페이스를 구현하는 추상 기본 클래스입니다. 구체적으로 구현하려면이 클래스에서 파생해야합니다. 어쨌든 Microsoft는 IComparer 인터페이스를 구현하는 대신 Comparer 클래스를 사용하는 것이 좋습니다.

Comparer 클래스는 IComparer.Compare 메서드의 명시 적 인터페이스 구현과 개체의 기본 비교자를 가져 오는 Default 속성을 제공하므로 IComparer 인터페이스를 구현하는 대신 Comparer 클래스에서 파생하는 것이 좋습니다.

요약

  • IComparer-두 가지를 정렬하고 비교합니다.
  • IComparable-FB에서 다른 사람과 자신을 비교합니다.

이야기가 기억하는 데 도움이되기를 바랍니다.


1
핵심 개념을 설명하는 방법이 마음에 듭니다. 이 대회에 Comparer (T) 클래스를 포함 시키면 더 좋을 것입니다. 질문에 포함되지 않더라도. :)
Kevman

4

다른 사람들이 말했듯이 그들은 같은 일을하지 않습니다.

어쨌든 요즘 나는 IComparer를 사용하지 않는 경향이 있습니다. 내가 왜? 그 책임 (두 개체를 비교하는 데 사용되는 외부 엔터티)은 대부분의 LINQ 메서드 작동 방식과 유사하게 람다 식을 사용하여 훨씬 더 깔끔하게 처리 할 수 ​​있습니다. 비교할 객체를 인수로 취하고 bool을 반환하는 빠른 람다를 작성합니다. 개체가 고유 한 비교 작업을 정의하는 경우 대신 IComparable을 구현할 수 있습니다.


1
-1 : 부울 반환은 IComparer와 동일하지 않습니다. IComparer는 0보다 작거나 / 0 / 0보다 클 수있는 값을 반환하며 일반적으로 정렬에 사용됩니다.
Joe

그리고 이것이 필요한 경우 대신 int (또는 더 나은 방법은 열거 형)를 반환합니다. 정말 큰일인가요?
jalf

2
시퀀스를 정렬하는 데 필요한 작업이보다 작기 때문에 bool을 반환 할 수도 있습니다.
jalf

IComparer 구현은 한 번만 정의하면됩니다. 더 많은 위치에서 정렬 논리를 사용해야하는 경우 람다 식을 더 많이 작성해야합니다.
oɔɯǝɹ 2010-02-06

oɔɯǝɹ-그런 다음 람다 식으로 작성된 대리자에 대한 참조를 저장할 수도 있습니다.
jpierson

3

IComparable은 개체를 다른 개체와 비교할 수 있다고 말합니다. IComparer는 두 항목을 비교할 수있는 개체입니다.


2

IComparer는 배열을 정렬하는 데 사용되는 인터페이스입니다.이 인터페이스는 클래스가 두 개체를 비교하는 Compare (T x, T y) 메서드를 구현하도록합니다. 이 인터페이스를 구현 한 클래스의 인스턴스는 Array의 정렬에 사용됩니다.

IComparable은 동일한 유형의 두 객체를 비교해야하는 유형으로 구현 된 인터페이스입니다.이 비교 가능한 인터페이스는 클래스가 다음 메소드 CompareTo (T obj)를 구현하도록 강제합니다.

IEqualityComparer는 객체가 Equal인지 아닌지를 찾는 데 사용되는 인터페이스입니다. 이제 컬렉션에서 Distinct of a Object를 찾아야하는 샘플에서 이것을 볼 것입니다. 이 인터페이스는 Equals (T obj1, T obj2) 메소드를 구현합니다.

이제 예제를 살펴보면 Employee 클래스가 있습니다.이 클래스를 기반으로 컬렉션을 만들어야합니다. 이제 다음 요구 사항이 있습니다.

배열 클래스 2를 사용하여 배열을 정렬합니다. Linq를 사용하여 컬렉션이 필요합니다. 중복 제거, 높은 순서에서 낮은 순서로 정렬, 직원 ID 하나 제거

abstract public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { set; get; }
}

public enum SortType
{
    ByID,
    BySalary
}

public class EmployeeIdSorter : IComparer {public int Compare (Employee x, Employee y) {if (x.Id <y.Id) return 1; 그렇지 않으면 (x.Id> y.Id) return -1; 그렇지 않으면 0을 반환합니다. }}

    public class EmployeeSalarySorter : IComparer<Employee>
    {
        public int Compare(Employee x, Employee y)
        {
            if (x.Salary < y.Salary)
                return 1;
            else if (x.Salary > y.Salary)
                return -1;
            else
                return 0;
        }
    }

자세한 내용은 http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html을 참조 하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.