IComparable arayüzü eski / “zararlı” mı?


11

IComparable sadece tek yönlü çalışır

Diyelim ki bir dersiniz var Employee. Bir görünümde, tüm Employeesadları ada göre sıralanmış olarak, diğerinde, adrese göre göstermek istersiniz . Bunu nasıl başaracaksınız? Değil ile IComparableen azından hiçbir deyimsel bir şekilde.

IComparable mantığı yanlış yerde tutmak

Arayüz çağrılarak kullanılır .Sort(). Ada göre Customersıralanmış bir görünümde , nasıl sıralanacağını gösteren hiçbir kod yoktur.
Öte yandan Customersınıf, nasıl kullanılacağını varsayar - bu durumda, isimlere göre sıralanmış bir listede kullanılacağını.

IComparable dolaylı olarak kullanılır

Alternatiflerle karşılaştırıldığında, karşılaştırma mantığının nerede kullanıldığını veya hiç olup olmadığını görmek çok zordur. Standart IDE'nizi varsayarak ve Customersınıftan başlayarak,

  1. İçin tüm referansları ara Customer
  2. Listede kullanılan referansları bulma
  3. Bu listelerin hiç .Sort()çağrılıp çağrılmadığını kontrol edin

Daha da kötüsü, IComparablehala kullanılmakta olan bir uygulamayı kaldırırsanız hata veya uyarı almazsınız. Alacağınız tek şey, düşünmeniz için çok karanlık olan her yerde yanlış davranış.

Bu sorunlar bir araya geldi ve değişen gereksinimler

Bunu düşünmeye başlamamın nedeni, benim için yanlış gitti. IComparable2 yıldır mutlu bir şekilde başvurumda kullanıyorum . Şimdi, gereksinimler değişti ve şeyin 2 farklı şekilde sıralanması gerekiyor. Önceki bölümde açıklanan adımlardan geçmenin eğlenceli olmadığını fark ettim.

Soru

Bu konular beni alternatifler tarafından daha iyi sunulmayacak geçerli bir kullanım durumu görmüyor ya IComparableda aşağı görmüyor. LINQ kullanmak her zaman daha mı iyidir , yoksa burada görmediğim avantajlar / kullanım durumları var mı?IComparer.OrderBy()
IComparer


2
Yeni "iki farklı şekilde sırala" gereksiniminiz kırmızı bir ringa balığıdır. Çözmek için yapmanız gereken tek şey sıralama işlevinize farklı bir karşılaştırıcı geçmek.
Robert Harvey

@RobertHarvey O zaman IComparableartık kullanmazsınız ki bu benim açımdan pekiştiriyor.
R. Schmitz

SortedXXXKoleksiyonları kullanırsanız , saklanan öğelerin olmasını IComparableveya sağlanmasını gerektirdiklerini unutmayın IComparer. Ayrıca, doğal sıralama düzenini tek bir karşılaştırıcıyla tersine çevirmenin ve tüm IComparablenesnelerle çalışmasını sağlamanın önemsiz olduğunu unutmayın .
Berin Loritsch

2
İki farklı arayüzün olması önemli değil. varsayılan karşılaştırma mekanizması IComparableolarak kabul edilir . , varsayılan karşılaştırma mekanizmasını geçersiz kılmak istediğinizde kullanılır. IComparer
Robert Harvey

Yanıtlar:


14

IComparablebahsettiğiniz kısıtlamalar vardır, bu doğrudur. Bu işlevsel alternatiflerin ve Linq'in mevcut olmadığı .NET framework 1.0'da zaten mevcut olan bir arabirimdir. Bu yüzden evet, temelde geriye dönük uyumluluk için tutulan eski bir çerçeve öğesi olarak görülebilir.

Bununla birlikte, birçok basit veri yapısı için, bir sınıflandırma yöntemi muhtemelen yeterli veya doğaldır. Bu durumlarda, sipariş ilişkisini uygulamak için bir kanonik yere sahip olmak, her OrderByyerde her çağrıda her zaman aynı mantığı tekrarlamak yerine DRY kodunu korumanın iyi bir yoludur .

Yazdığınız gibi "2 yıldır uygulamanızda mutlu bir şekilde IComparable'ı kullanıyorsunuz", bu yüzden bana uzun zamandır iyi hizmet etti. Artık tüm çağrıları doğrulamanız, değiştirmeniz ve test etmeniz gerektiğinde Sort, bu aynı zamanda birçok yerde aynı tür bir sıralama mantığı yaptığınızın bir işareti olabilir, ki bu da hata değildir IComparable. Bu, bu mantığın daha fazlasını tek bir yerde merkezileştirmek ve kodunuzu daha KURU yapmak için bir fırsat olabilir.


Basit veri yapıları hakkında iyi bir nokta. Ancak, son paragraf benim için% 100 mantıklı değil. Eğer kullanmamış olsaydım IComparable, önceden var olan tüm sıralama kodu kendi görünümlerinde dokunulmadan bırakılırken, yalnızca yeni görünüm için yeni sıralama kodu eklerdim.
R. Schmitz

@ R.Schmitz Önceden var olan sıralama, IComparableyazdığınız uygulama olmadan doğru şekilde çalışır mı?
Robert Harvey

3
@ R.Schmitz: Tabii, ama şimdi her zaman bir karşılaştırıcı sağlamayı taahhüt ediyorsunuz (tabii ki OrderBy kullanmıyorsanız). İle IComparable, ücretsiz bir varsayılan uygulama alırsınız ve bazen bu uygulamayı yazmak zorunda bile kalmazsınız.
Robert Harvey

2
@ R.Schmitz: Oradaki son yorumunuz güzel bir şekilde özetleniyor. Yine de biraz daha ileri giderdim. Diyelim ki sayısal bir tipiniz var BigInteger. Karşılaştırma işleçlerini / arabirimlerini uygulamadıysa, bir IComparer'ı nasıl kendiniz uygularsınız ? Verimli veya hiç yapmak için dahili veri yapılarına erişmeniz gerekir. Diyelim ki Müşteri gibi bir türünüz var; Kamu özellikler üzerinde sıralamak istiyoruz do comparers var. Uygulamak: Benim için bu fark IComparable<T>olurdu eğer mantıksız bir karşılaştırıcısı uygulamak için arayan beklemek.
Eric Lippert

1
If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.Çünkü IComparablebir oldu daha iyi bir çözüm zamanda , bu demek değildir iyi çözüm bugün . Buradaki ilk yorumunuz, "bu değişmez ya da hiçbir şey" anlamına gelmez, ki bu doğru değildir, sorun birçok farklı şekilde çözülmüş olabilir. Uygulamalar boyut / ölçek olarak büyüyebilir ve uygun görünen şeyler uygulamanın artan taleplerine ayak uyduramayabilir.
flater

1

Hakkındaki görüşlerinize katılıyorum IComparable

Şu konudaki açıklamalara bakın: Array.Sort()

  • Dizinin her öğesinin, dizideki IComparablediğer tüm öğelerle karşılaştırma yapabilmesi için arabirimi uygulaması gerekir . (veya istisna atılır)
  • Sıralama başarıyla tamamlanmazsa, sonuçlar tanımsız olur.

Muhtemelen şimdi asla motivasyon olmayacak, Ancak! object.Equals()her nesnede, nesneleri “aynı” olup olmadıklarını görmek için birbirleriyle karşılaştırmanıza olanak veren bir yöntem düşünün

Zaten orada var, ancak Array.Sort()eklemek istendiğinde eklemek isteyebilirsinizobject.Compare(object)

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.