IComparableインターフェイスとIEquatableインターフェイスの違いは何ですか?


97

どちらのインターフェースもオブジェクトが等しいかどうかを比較しているようですが、それらの主な違いは何ですか?

回答:


188

IEquatable 2つのオブジェクトが等しいかどうかをテストします。

IComparable 比較されるオブジェクトに完全な順序付けを課します。

たとえばIEquatable、5は7 IComparableと等しくないことを 示します。5は7の前にあることを示します。



10

グレッグDの答えに加えて:

部分的な順序付けが意味をなすクラスを実装IComparableせずに実装IEquatableし、CompareTo()ゼロを返すからといって消費者にそれを確実に推測させたい場合、これオブジェクトが等しいことを意味するわけではありません(並べ替え以外の目的で)。


10
これは、オブジェクトがIComparable適切に実装されているのではなく、特別な場合の比較のように聞こえます。が平等を意味CompareTo(…) == 0ない意味のある例を思いつきますか?私は確かにできません。実際、インターフェイスコントラクト(MSDNによる)ではCompareTo(…) == 0同等であることを意味します。率直に言って、あなたのような場合は、特別なComparatorオブジェクトを使用し、実装しないでくださいIComparable
Konrad Rudolph

2
@Konrad-私はいくつかの警告を示しました-タイプがIEquatableを実装していないこと(したがって、オリジネーターは等価テストを含めたくない)、そしてCompareToの結果は、等価を評価するためではなく、ソートに使用されることです。また、どの同等性が関連しているかについての質問にも答えます(参照、値、「任意」の属性は無視します。長さが500ページのブルーブックは、長さが500ページのレッドブックと同じです。IComparableの場合)。
Damien_The_Unbeliever

4
あなたの最後の文は間違っています、そしてこれは私が指摘したかった特定の間違いです:IComparableここでは完全に不適切です。入手できるのは、1つの特別な状況でのみ適用される非常に特殊な順序です。このような状況では、将軍の実装IComparableは間違っています。これIComparerが目的です。たとえば、人々は意味のある注文をすることができません。ただし、給与、靴のサイズ、そばかすの数、または体重に応じて注文できます。したがって、IComparerこれらすべてのケースに異なるを実装します。
Konrad Rudolph

2
@Konrad Rudolph:特定の時間に「何か」を行うことになっている「ScheduledEvent」クラスのようなものはどうですか?このタイプのセマンティクスは、アクションが発生するはずのタイミングに基づいた非常に強力な自然なセマンティクスの順序を意味しますが、同時に異なるイベントが発生する可能性があります。手動で指定したIComparerを使用する必要があるかもしれませんが、クラスにコンパレーターを組み込む方が便利だと思います。
スーパーキャット'23 / 11/11

4
@supercat利便性は重要ですが、それだけではありません。正確性(論理的な一貫性など)はより重要であり、静的型システムはこの論理的な一貫性を検証するための重要なツールです。実装するインターフェースの文書化された規約に違反することにより、型システムを覆すことになります。これは良い考えではないので、お勧めしません。このような状況では、外部コンパレータを使用してください。
Konrad Rudolph

7

IEquatableMSDNページで述べたように:

IComparableインターフェイスはCompareTo、実装するタイプのインスタンスのソート順を決定するメソッドを定義します。IEquatableインターフェイスはEquals、実装するタイプのインスタンスの同等性を決定するメソッドを定義します。

EqualsCompareTo


2

IComparable <T> オブジェクトの順序付けまたはソートに使用できるタイプ固有の比較メソッドを定義します。

IEquatable <T> 同等性を決定するための実装に使用できる一般化された方法を定義します。


Personクラスがあるとしましょう

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Person p1 = new Person() { Name = "Person 1", Age = 34 };
Person p2 = new Person() { Name = "Person 2", Age = 31 };
Person p3 = new Person() { Name = "Person 3", Age = 33 };
Person p4 = new Person() { Name = "Person 4", Age = 26 };

List<Person> people = new List<Person> { p1, p2, p3, p4 };

これらのオブジェクトをソートするには、使用できます people.Sort();

しかし、これは例外をスローします。

ここに画像の説明を入力してください

フレームワークはこれらのオブジェクトをソートする方法を知りません。実装するIComparableインターフェイスを並べ替える方法を伝える必要があります。

public class Person : IComparable
{
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(object obj)
    {
        Person otherPerson = obj as Person;
        if (otherPerson == null)
        {
            throw new ArgumentNullException();
        }
        else
        {
            return Age.CompareTo(otherPerson.Age);
        }
    }
}

これは配列を正しく並べ替えます Sort()メソッドで。


次に、Equals()メソッドを使用して2つのオブジェクトを比較します。

var newPerson = new Person() { Name = "Person 1", Age = 34 };
var newPersonIsPerson1 = newPerson.Equals(p1);

これはfalseEqualsメソッドが2つのオブジェクトを比較する方法を知らないために返されます。したがってIEquatable、インターフェースを実装し、フレームワークに比較方法を伝える必要があります。前の例を拡張すると、次のようになります。

public class Person : IComparable, IEquatable<Person>
{
    //Some code hidden

    public bool Equals(Person other)
    {
        if (Age == other.Age && Name == other.Name)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

1
この素晴らしい説明をありがとう。質問:なぜIEquatableジェネリック<Person>を使用し、使用IComparableしないのですか?
-veuncent
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.