Apa perbedaan antara antarmuka IComparable & IEquatable?

97

kedua antarmuka tampaknya membandingkan objek untuk persamaan, jadi apa perbedaan utama di antara keduanya?

SoftwareGeek
sumber

Jawaban:

188

IEquatable menguji apakah dua objek sama.

IComparable memaksakan pemesanan total pada objek yang dibandingkan.

Misalnya, IEquatableakan memberi tahu Anda bahwa 5 tidak sama dengan 7. IComparableakan memberi tahu Anda bahwa 5 datang sebelum 7.

Greg D
sumber
20

IEquatable<T> untuk kesetaraan.

IComparable<T> untuk memesan.

Islam Yahiatene
sumber
10

Selain jawaban Greg D:

Anda dapat mengimplementasikan IComparabletanpa mengimplementasikan IEquatableuntuk kelas yang pengurutan parsial masuk akal, dan di mana Anda sangat ingin konsumen menyimpulkan bahwa hanya karena CompareTo()mengembalikan nol, ini tidak berarti bahwa objeknya sama (untuk apa pun selain tujuan pengurutan).

Damien_The_Tidak percaya
sumber
10
Kedengarannya jauh lebih seperti pembanding kasus khusus daripada seperti objek yang diterapkan IComparabledengan benar. Anda bisa datang dengan contoh yang berarti di mana CompareTo(…) == 0tidak tidak menyiratkan kesetaraan? Saya pasti tidak bisa. Faktanya, kontrak antarmuka (sesuai MSDN) mensyaratkan yang CompareTo(…) == 0menyiratkan kesetaraan. Terus terang, dalam kasus seperti Anda, gunakan khusus Comparatorobjek, jangan tidak menerapkan IComparable.
Konrad Rudolph
2
@Konrad - Saya memang menunjukkan beberapa peringatan - bahwa jenisnya tidak mengimplementasikan IEatable (jadi jelas, pembuatnya tidak ingin menyertakan uji kesetaraan), dan hasil CompareTo digunakan untuk menyortir, bukan untuk mengevaluasi kesetaraan. Anda juga mendapat pertanyaan tentang kesetaraan mana yang relevan (referensi, nilai, mengabaikan atribut "sewenang-wenang" - buku biru dengan panjang 500 halaman mungkin "sama" dengan buku merah sepanjang 500 halaman, untuk tujuan IComparable)
Damien_The_Unbeliever
4
Kalimat terakhir Anda salah, dan inilah kesalahan khusus yang ingin saya tunjukkan: IComparablesama sekali tidak pantas di sini. Apa yang Anda dapatkan adalah urutan yang sangat khusus yang hanya berlaku dalam satu situasi khusus. Untuk situasi seperti itu, menerapkan seorang jenderal IComparableadalah salah. Untuk inilah IComparerada. Misalnya, orang tidak bisa diatur secara bermakna. Tetapi mereka dapat dipesan berdasarkan gaji, ukuran sepatu, jumlah bintik atau beratnya. Oleh karena itu, kami akan menerapkan berbeda IComparerkarena semua kasus ini.
Konrad Rudolph
2
@Konrad Rudolph: Bagaimana dengan sesuatu seperti kelas "ScheduledEvent", yang seharusnya melakukan "sesuatu" pada waktu tertentu? Semantik dari jenis tersebut akan menyiratkan urutan semantik alami yang sangat kuat berdasarkan pada saat tindakan seharusnya terjadi, tetapi seseorang dapat dengan mudah memiliki peristiwa berbeda yang terjadi pada saat yang sama. Seseorang dapat memerlukan penggunaan IComparer yang ditentukan secara manual, tetapi saya ingin memastikan bahwa memiliki komparator yang dibangun ke dalam kelas akan lebih nyaman.
supercat
4
@supercat Kenyamanan itu penting, tetapi ini bukanlah segalanya. Ketepatan (seperti dalam, konsistensi logis) lebih penting dan sistem tipe statis merupakan alat penting untuk memverifikasi konsistensi logis ini. Dengan melanggar kontrak antarmuka yang didokumentasikan yang Anda implementasikan, Anda menumbangkan sistem tipe. Ini bukan ide yang bagus, dan saya tidak akan merekomendasikannya. Gunakan pembanding eksternal untuk situasi seperti itu.
Konrad Rudolph
7

Seperti yang dinyatakan di Halaman MSDN untuk IEquatable :

Antarmuka IComparable mendefinisikan CompareTometode, yang menentukan urutan pengurutan instance dari tipe implementasi. Antarmuka IEquatable mendefinisikan Equalsmetode, yang menentukan persamaan contoh dari tipe implementasi.

Equals vs. CompareTo

Will Eddins
sumber
2

IComparable <T> mendefinisikan metode perbandingan khusus tipe yang dapat digunakan untuk memesan atau mengurutkan objek.

IEquatable <T> mendefinisikan metode umum yang dapat digunakan untuk diterapkan dalam menentukan kesetaraan.


Katakanlah Anda memiliki kelas 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 };

Untuk mengurutkan benda-benda ini dapat Anda gunakan people.Sort();.

Tapi ini akan membuat pengecualian.

masukkan deskripsi gambar di sini

Kerangka tidak tahu cara mengurutkan objek ini. Anda perlu memberi tahu cara mengurutkan IComparableantarmuka penerapan .

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);
        }
    }
}

Ini akan mengurutkan array dengan benar dengan Sort()metode.


Selanjutnya untuk membandingkan dua objek, Anda dapat menggunakan Equals()metode.

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

Ini akan kembalifalse karena Equalsmetode tidak tahu bagaimana membandingkan dua objek. Oleh karena itu, Anda perlu mengimplementasikan IEquatableantarmuka dan memberi tahu framework cara melakukan perbandingan. Memperluas contoh sebelumnya akan terlihat seperti ini.

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;
        }
    }
}
Nipuna
sumber
1
Terima kasih atas penjelasan yang bagus ini. Pertanyaan: mengapa IEquatablemenggunakan generik <Person>dan IComparabletidak?
veuncent