IComparable ve IEquatable arayüzleri arasındaki fark nedir?


Yanıtlar:


189

IEquatable iki nesnenin eşit olup olmadığını test eder.

IComparable karşılaştırılan nesnelere tam bir sıralama uygular.

Örneğin, IEquatable5'in 7'ye eşit olmadığını IComparablesöylerseniz 5'in 7'den önce geldiğini söylersiniz.



10

Greg D'nin cevabına ek olarak:

Kısmi bir sıralamanın anlamlı olduğu ve tüketicinin kesinlikle sıfır döndürdüğü için bunun nesnelerin eşit olduğu anlamına gelmediğini (sıralama amaçlarından başka herhangi bir şey için) anlamasını istediğiniz bir sınıf için uygulama IComparableyapmadan uygulayabilirsiniz .IEquatableCompareTo()


10
Bu, IComparabledoğru bir şekilde uygulanan bir nesneden çok özel bir durum karşılaştırmasına benziyor . Eğer anlamlı bir örnekle anlatabilir misin CompareTo(…) == 0yok değil eşitlik ima? Kesinlikle yapamam. Aslında, arayüz sözleşmesi (MSDN göre) gerektiren bu CompareTo(…) == 0eşitliği ima eder. Senin, özel bir kullandıkça böyle bir durumda, açıkça söylemek gerekirse Comparatornesne yok değil uygulamak IComparable.
Konrad Rudolph

2
@Konrad - Birkaç uyarı belirttim - türün IEquatable'ı uygulamadığını (açıkçası, yaratıcı bir eşitlik testi dahil etmek istemiyor) ve CompareTo sonuçlarının eşitliği değerlendirmek için değil sıralama için kullanıldığını . Aynı zamanda eşitliğin ilgili olduğu sorulara da girersiniz (referans, değer, "keyfi" öznitelikleri göz ardı ederek - 500 sayfa uzunluğunda bir mavi kitap, IComparable amaçları doğrultusunda, 500 sayfalık kırmızı bir kitaba "eşit" olabilir)
Damien_The_Unbeliever

4
Son cümlenin yanlış ve bu, özellikle belirtmek istediğim hata: IComparableburada tamamen uygunsuz. Sahip olduğunuz şey , yalnızca tek bir özel durumda geçerli olan çok özel bir sıralama. Bu tür durumlarda, bir generalin uygulanması IComparableyanlıştır. Bunun ICompareriçin var olanlar. Örneğin, insanlar anlamlı bir şekilde sıralanamaz. Ama olabilir maaşlarının onların ayakkabı numarası, onların çiller veya ağırlık sayılarına göre sipariş edilmelidir. Dolayısıyla, IComparertüm bu durumlar için farklı ' ler uygularız .
Konrad Rudolph

2
@Konrad Rudolph: Belirli bir zamanda "bir şeyler" yapması gereken "ScheduledEvent" sınıfı gibi bir şeye ne dersiniz? Türün semantikleri, eylemin gerçekleşmesi gereken zamana dayanan çok güçlü bir doğal anlamsal sıralama anlamına gelir, ancak aynı anda farklı olaylar kolayca meydana gelebilir. Manuel olarak belirtilen bir IComparer'ın kullanılması gerekebilir, ancak sınıfa yerleştirilmiş bir karşılaştırıcıya sahip olmanın daha uygun olacağını düşünürdüm.
supercat

4
@supercat Rahatlık önemlidir, ancak her şey değildir. Doğruluk (mantıksal tutarlılıkta olduğu gibi) daha önemlidir ve statik tip sistemi bu mantıksal tutarlılığı doğrulamak için önemli bir araçtır. Uyguladığınız belgelenmiş arayüz sözleşmesini ihlal ederek, tip sistemini altüst etmiş olursunuz. Bu iyi bir fikir değil ve asla tavsiye etmem. Bu tür durumlar için harici bir karşılaştırıcı kullanın.
Konrad Rudolph

7

IEquatable için MSDN Sayfasında belirtildiği gibi :

IComparable arabirimi CompareTo, uygulama türünün örneklerinin sıralama düzenini belirleyen yöntemi tanımlar . IEquatable arabirimi Equals, uygulama türünün örneklerinin eşitliğini belirleyen yöntemi tanımlar .

Equals vs. CompareTo


3

IComparable <T> nesneleri sıralamak veya sıralamak için kullanılabilen türe özgü bir karşılaştırma yöntemi tanımlar.

IEquatable <T> Eşitliği belirlemek için uygulanabilecek genelleştirilmiş bir yöntemi tanımlar.


Diyelim ki kişi sınıfınız var

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

Bu nesneleri sıralamak için kullanabilirsiniz people.Sort();.

Ancak bu bir istisna yaratacaktır.

görüntü açıklamasını buraya girin

Framework bu nesneleri nasıl sıralayacağını bilmiyor. Uygulama IComparablearayüzünü nasıl sıralayacağınızı söylemeniz gerekir .

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

Bu, diziyi Sort()yöntemle doğru şekilde sıralayacaktır .


İki nesneyi karşılaştırmak için Equals()yöntemi kullanabilirsiniz .

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

Bu dönecektirfalse çünkü Equalsyöntem iki nesneleri karşılaştırmak için nasıl bilmiyor. Bu nedenle, IEquatablearayüzü uygulamanız ve çerçeveye karşılaştırmanın nasıl yapılacağını söylemeniz gerekir . Önceki örneğe genişletirsek, şöyle görünecektir.

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
Bu harika açıklama için teşekkürler. Soru: neden IEquatablejenerik kullanıyor <Person>ve kullanmıyor IComparable?
veuncent
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.