IComparable <T> Vs. ne zaman kullanılır? IComparer <T>


Yanıtlar:


96

Pekala , iki farklı nesneyi karşılaştırabilen bir tür üzerinde uygulanmış olanla tam olarak aynı şey değildirler , ancak aynı türden diğer örneklerle kendilerini karşılaştırabilen türlerde uygulanır.IComparer<T>IComparable<T>

IComparable<T>Başka bir örneğin örnekle nasıl ilişkili olduğunu bilmem gereken zamanlar için kullanma eğilimindeyim this. karşılaştırmanın dışında IComparer<T>olduğu için koleksiyonları sıralamak için kullanışlıdır IComparer<T>.


9
IComparer <T>, istediğiniz her tür sıralama için bir sınıfa sahip olmanıza da olanak tanır. Misal; PersonLastFirstNameComparer, PersonFirstLastNameComparer veya PersonAgeComparer.
Eric Schneider

Onları hatırlamanın kolay bir yolu var mı? Her seferinde bakmak zorunda kalıyorum.
amadib

59
düşünmek @amadib IComparableolarak ben karşılaştırılabilir değilim . bu da başka bir şeyle karşılaştırılabileceğim anlamına geliyor. Ve okundu IComparerolarak ben comparer değilim, ben sadece karşılaştırmak Bazı şeyleri karşılaştırmak hangi araçlar.
nawfal

@newfal Bunu bir cevap olarak koymalıydın. Bence buradaki en iyi açıklama bu.
Gene S

42

IComparable<T>Sınıfın içsel bir karşılaştırması olduğunda kullanın .

IComparer<T>Varsa, sınıfın iç karşılaştırması dışında bir karşılaştırma yöntemi istediğinizde kullanın .


28

Varlığa bağlıdır. Örneğin "Öğrenci" gibi bir sınıfı takip etmek, Ada göre IComparable'a sahip olmak mantıklı olacaktır.

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

Ancak bir öğretmen 'A' öğrencileri MathScore'a göre karşılaştırmak istiyorsa ve öğretmen 'B' öğrencileri EnglishScore'a göre karşılaştırmak istiyorsa. IComparer'ı ayrı olarak uygulamak iyi bir fikir olacaktır. (Daha çok bir strateji modeli gibi)

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

Karşılaştırma yöntemini kullanım kolaylığı için statik hale getirin.
Ocak

9

Her şey türünüzün değiştirilebilir olup olmadığına bağlıdır. Sen olmalıdır yalnızca olmayan değişken türleri üzerinde IComparable uygulamak. IComparable'ı uygularsanız, ==,! =, <Ve> operatörleriyle birlikte Eşittir'i geçersiz kılmanız gerektiğini unutmayın (bkz. Kod Analizi uyarısı CA1036).

Dave G'den bu blog gönderisinden alıntı :

Ancak doğru yanıt, nesneleriniz değiştirilebilirse IComparable yerine IComparer uygulamak ve gerektiğinde IComparer'ın bir örneğini sıralama işlevlerine geçirmektir.

IComparer, yalnızca o noktada sıralama için kullanılan tek kullanımlık bir nesne olduğundan, nesneniz arzu ettiğiniz herhangi bir değiştirilebilir semantiğe sahip olabilir. Dahası, Eşittir, GetHashCode veya == kullanılmasını gerektirmez ve hatta önermez - dilediğiniz şekilde tanımlayabilirsiniz.

Son olarak, farklı alanlarda veya farklı kurallarla sıralama yapmak için türünüz için birden çok IComparer tanımlayabilirsiniz. Bu, tek bir tanıma bağlı kalmaktan çok daha esnektir.

Kısaca: Değer türleri için IComparable'ı ve başvuru türleri için IComparer'ı kullanın.


6

Bir hikaye üzerinden basit açıklama

Lise basketbolu. Takımlar için bir okul bahçesi seçimi. Takımımdaki en uzun / en iyi / en hızlı insanları almak istiyorum. Ben ne yaparım?

IComparer Arayüzü - İki kişiyi ayrı ayrı karşılaştırın

  • Bu, sıraya giren herhangi iki adamı karşılaştırmama izin veriyor ......... temelde bu. Fred vs John .......... Onları arayüzü uygulayan somut bir sınıfa atıyorum. Compare(Fred, John)ve kimin daha iyi olduğunu ortaya çıkarır.

IComparable ne olacak? - Kendinizi başka biriyle karşılaştırın

Son zamanlarda FB'de bulundunuz mu? Diğer insanların harika şeyler yaptığını görüyorsunuz: dünyayı dolaşmak, icatlar yaratmak, ben pek de havalı olmayan bir şey yaparken - yaptığımız şey IComparable arayüzünü kullanmak.

  • Mevcut durumu (kendiniz) aynı türden (kişi) başka bir nesneyle (başka biri) karşılaştırıyoruz.

Karşılaştırma Sınıfı ne olacak?

Comparer sınıfı, IComparer arabirimini uygulayan soyut bir temel sınıftır. Somut bir uygulamaya sahip olmak için bu sınıftan türetmelisiniz. her neyse, Microsoft, IComparer arabirimini uygulamak yerine Comparer sınıfını KULLANMANIZI önerir:

Comparer sınıfı, IComparer.Compare yönteminin açık bir arabirim uygulaması ve nesne için varsayılan karşılaştırıcıyı alan Default özelliği sağladığından, IComparer arabirimini uygulamak yerine Comparer sınıfından türetmenizi öneririz.

Özet

  • IComparer - iki şeyi sıralayın ve karşılaştırın.
  • IComparable - kendinizi FB'deki diğerleriyle karşılaştırın.

Umarım hikayeler hatırlamana yardımcı olur.


1
Anahtar kavramı açıklama şeklinizi beğendim. Comparer (T) sınıfını bu yarışmaya dahil etmeniz daha iyi olabilir. Hatta soruya dahil değil. :)
Kevman

4

Başkalarının da söylediği gibi, aynı şeyi yapmazlar.

Her durumda, bu günlerde IComparer'ı kullanmıyorum. Neden yapayım? Sorumluluğu (iki nesneyi karşılaştırmak için kullanılan harici bir varlık), LINQ yöntemlerinin çoğunun nasıl çalıştığına benzer şekilde, bir lambda ifadesi ile çok daha temiz bir şekilde ele alınabilir. Karşılaştırmak için nesneleri argüman olarak alan ve bir bool döndüren hızlı bir lambda yazın. Ve nesne kendi içsel karşılaştırma işlemini tanımlıyorsa, bunun yerine IComparable'ı uygulayabilir.


1
-1: Bool döndürmek, IComparer ile eşdeğer değildir. IComparer, sıfırdan küçük / sıfırdan büyük olabilen ve genellikle sıralama için kullanılan bir değer döndürür.
Joe

Ve ihtiyacınız olan şey bu olduğunda, bunun yerine bir int (veya daha iyisi bir enum) döndürürsünüz. Bu gerçekten önemli mi?
jalf

2
Bir diziyi sıralamak için ihtiyacınız olan tek işlemden daha az olduğu için bir bool bile döndürebilirsiniz.
jalf

bir IComparer uygulamasının yalnızca bir kez tanımlanması gerekir, eğer sıralama mantığını daha fazla yerde kullanmanız gerekiyorsa, lambda ifadesinin daha fazla kez yazılması gerekecektir.
oɔɯǝɹ

oɔɯǝɹ - Daha sonra, lambda ifadesi olarak yazılan temsilciye bir referans depolayabilirsiniz, onu da yeniden kullanabilirsiniz.
jpierson

3

IComparable, bir nesnenin diğeriyle karşılaştırılabileceğini söylüyor. IComparer, herhangi iki öğeyi karşılaştırabilen bir nesnedir.


2

IComparer, Diziyi sıralamak için kullanılan bir arabirimdir, bu arabirim sınıfı, iki nesneyi karşılaştıracak olan Karşılaştır (T x, T y) yöntemini uygulamaya zorlar. Bu arabirimi uygulayan sınıfın örneği, Dizinin sıralanmasında kullanılır.

IComparable, aynı türdeki iki nesneyi karşılaştırması gereken türde uygulanan bir arabirimdir, Bu karşılaştırılabilir arabirim, sınıfı aşağıdaki yöntemi CompareTo (T obj) uygulamaya zorlayacaktır.

IEqualityComparer, nesneyi Eşit olsun ya da olmasın bulmak için kullanılan bir arayüzdür, Şimdi bunu bir Nesnenin Farkını bir koleksiyonda bulmamız gereken bir örnekte göreceğiz. Bu arayüz bir Eşit yöntem uygulayacak (T obj1, T obj2)

Şimdi bir Örnek alıyoruz, bir Çalışan sınıfımız var, bu sınıfa dayalı olarak bir Koleksiyon oluşturmamız gerekiyor. Şimdi aşağıdaki gereksinimlerimiz var.

Diziyi Array sınıfı 2 kullanarak sıralayın. Linq kullanarak bir koleksiyona ihtiyacınız var: Yinelemeyi kaldırın, Yukarıdan aşağıya sıralayın, Bir çalışan kimliğini kaldırın

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; aksi takdirde (x.Id> y.Id) -1 döndürür; aksi takdirde 0 döndürür; }}

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

Daha fazla bilgi için aşağıdaki hakem http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

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.