IComparable <T>をいつ使用するか。IComparer <T>


回答:


96

まあそうではありません、非常に同じことIComparer<T>ながら、2つの異なるオブジェクトを比較することのできるタイプに実装されているIComparable<T>同じ種類の他のインスタンスと自分を比較することができますタイプに実装されています。

IComparable<T>別のインスタンスがインスタンスにどのように関連しているかを知る必要があるときに使用する傾向がありthisます。 比較の外に立つIComparer<T>ので、コレクションをソートするのに役立ちIComparer<T>ます。


9
IComparer <T>では、必要な並べ替えの種類ごとにクラスを作成することもできます。例; PersonLastFirstNameComparer、PersonFirstLastNameComparer、またはPersonAgeComparer。
Eric Sc​​hneider

それらを覚えておく簡単な方法はありますか?毎回調べなければならない傾向があります。
amadib 2012年

59
考える@amadib IComparableとして、私は比較可能です。つまり、他の何かと比較することができます。そして、読みIComparerとして、私は比較演算子だ、私は単純に比較し、私はいくつかのことを比較することを意味します。
nawfal

@newfalこれを答えにするべきだった。ここが一番いい説明だと思います。
Gene S

42

IComparable<T>クラスに固有の比較がある場合に使用します。

IComparer<T>クラスに固有の比較がある場合は、それ以外の比較メソッドが必要な場合に使用します。


28

エンティティによって異なります。たとえば、「学生」のようなクラスの場合、名前に基づいて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を定義できます。これは、1つの定義に固執するよりもはるかに柔軟です。

つまり 、値の型にはIComparableを使用し、参照型にはIComparerを使用します。


6

ストーリーによる簡単な説明

高校バスケットボール。チームのための校庭ピックです。私のチームで最も背が高い/最高の/最速の人々を獲得したいと思います。私は何をしますか?

IComparerインターフェイス-2人を別々の人と比較する

  • これにより、並んでいる2人の男性を比較することができます…………基本的にはそれだけです。フレッド対ジョン..........私はそれらをインターフェースを実装する具象クラスに入れます。Compare(Fred, John)そしてそれは誰がより良いのかを吐き出します。

IComparableはどうですか?-自分を他の人と比較する

最近FBに行ったことがありますか?あなたは他の人々がクールなことをしているのを見ます:私はそれほどクールではない何かをしている間、世界を旅し、発明を作ります-私たちがやっていることはIComparableインターフェースを利用しています。

  • 現在のインスタンス(自分)を同じタイプ(人)の別のオブジェクト(他の誰か)と比較しています。

Comparerクラスはどうですか?

Comparerクラスは、IComparerインターフェイスを実装する抽象基本クラスです。具体的な実装を行うには、このクラスから派生する必要があります。とにかく、マイクロソフトでは、IComparerインターフェイスを実装するのではなく、Comparerクラスを使用することをお勧めします。

Comparerクラスは、IComparer.Compareメソッドの明示的なインターフェイス実装とオブジェクトのデフォルトの比較子を取得するDefaultプロパティを提供するため、IComparerインターフェイスを実装する代わりに、Comparerクラスから派生することをお勧めします。

概要

  • IComparer-2つのものを並べて比較します。
  • IComparable-FBで他の人と自分を比較します。

ストーリーがあなたの記憶に役立つことを願っています。


1
重要な概念を説明する方法が好きです。このコンテストにComparer(T)クラスを含めると、より良い結果が得られます。質問には含まれていません。:)
ケフマン

4

他の人が言ったように、彼らは同じことをしません。

いずれにせよ、最近はIComparerを使わない傾向があります。なぜ私は?その責任(2つのオブジェクトを比較するために使用される外部エンティティ)は、ほとんどのLINQのメソッドが機能するのと同様に、ラムダ式を使用してよりクリーンに処理できます。比較するオブジェクトを引数として取り、ブール値を返す簡単なラムダを記述します。また、オブジェクトが固有の比較操作を定義している場合は、代わりにIComparableを実装できます。


1
-1:boolを返すことは、IComparerと同等ではありません。IComparerは、ゼロ未満/ゼロ/ゼロより大きい値を返すことができ、通常はソートに使用されます。
ジョー

そして、それが必要な場合は、代わりにint(より良いのは列挙型)を返します。それは本当に大したことですか?
jalf

2
シーケンスをソートするために必要な操作は「より小さい」だけなので、ブール値を返すこともできます。
jalf

IComparer実装を定義する必要があるのは1回だけです。並べ替えロジックをより多くの場所で使用する必要がある場合は、ラムダ式を何度も記述する必要があります。
oɔɯǝɹ

oɔɯǝɹ-次に、ラムダ式として記述されたデリゲートへの参照を格納して、それを再利用できます。
jpierson 2011

3

IComparableは、オブジェクトを別のオブジェクトと比較できると言います。IComparerは、任意の2つの項目を比較できるオブジェクトです。


2

IComparerは、配列の並べ替えに使用されるインターフェイスです。このインターフェイスは、2つのオブジェクトを比較するCompare(T x、T y)メソッドの実装をクラスに強制します。このインターフェースを実装したクラスのインスタンスは、配列のソートに使用されます。

IComparableは、同じタイプの2つのオブジェクトを比較する必要があるタイプで実装されているインターフェースです。この比較可能なインターフェースにより、クラスは次のメソッドCompareTo(T obj)を実装します。

IEqualityComparerは、Equalであるかどうかに関係なくオブジェクトを見つけるために使用されるインターフェイスです。これを、コレクション内のオブジェクトのDistinctを見つける必要があるサンプルで確認します。このインターフェイスは、メソッドEquals(T obj1、T obj2)を実装します

今度はEmployeeクラスがある例を取り上げます。このクラスに基づいて、コレクションを作成します。現在、次の要件があります。

配列クラス2を使用して配列をソートします。Linqを使用してコレクションが必要です。重複を削除し、上位から下位に並べ替え、従業員IDを1つ削除します

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

public enum SortType
{
    ByID,
    BySalary
}

パブリッククラスEmployeeIdSorter:IComparer {public int Compare(Employee x、Employee y){if(x.Id <y.Id)return 1; else if(x.Id> y.Id)は-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.