2009-02-02 12 views
7

OK, więc mam scenariusz podobny do poniższego kodu, mam klasy nadrzędnej, która implementuje IComparable i klasy potomnej.Mam problem z IComparable i metoda sortowania kolekcji

class Parent : IComparable<Parent> 
class Child : Parent 

Child a = new Child(); 
Child b = new Child(); 
a.CompareTo(b); 

Teraz powyższe prace w porządku, mogę porównać dwa dziecka sprzeciwia się nawzajem bez problemu

List<Child> l = new List<Child>(); 
l.Add(b); 
l.Add(a); 
l.Sort(); 

Powyższy zawiedzie choć InvalidOperationException. Czy ktoś może wyjaśnić, dlaczego ten rodzaj nie działa, gdy klasa potomna implementuje interfejs IComparable, a przynajmniej wydaje mi się, że tak.

Dobrze tu jest mój realizacja CompareTo dla mojego rzeczywistej klasy nadrzędnej

public int CompareTo(IDType other) 
{ 
     return this.Name.ToString().CompareTo(other.ToString()); 
} 
+0

próbka mówi „new List ()”, który zgaduję to literówka ... co jest rzeczywisty typ rodzajowy na listę, którą tworzysz? –

+0

O tak, przepraszam, to był literówka, miałem listę l = nowa lista (); Myślę, że to dość oczywiste, jaką generyczną listę typów tworzyłem. – CalvinR

+0

Czy możemy zobaczyć kod z twojej implementacji IComparable? –

Odpowiedz

6

Twój typ implementuje IComparable<Parent> zamiast IComparable<Child>. Jak mówi MSDN docs for Sort, wywoła to InvalidOperationException, jeśli "domyślny Porównawcznik Porównawczy (T) .Default nie może znaleźć implementacji interfejsu ogólnego (T) IComparable lub interfejsu IComparable dla typu T." I rzeczywiście nie może, gdzie T jest dzieckiem. Jeśli spróbujesz to zrobić, to może się okazać, że wszystko jest w porządku.

EDYCJA: Alternatywnie (a najlepiej, IMO) implementuj IComparable<Child>. W tej chwili nie jest wcale jasne, czy dziecko można rozsądnie porównać z innym dzieckiem. Wdrażanie IComparable<Child> - nawet jeśli ta implementacja po prostu odsuwa się od implementacji podstawowej - reklamuje porównywalność.

+0

Żadne porównanie nie działa dobrze, używam tylko funkcji porównywania zmiennej składowej łańcuchowej, która jest przechowywana w klasie nadrzędnej. – CalvinR

+0

Zmieniona odpowiedź całkowicie teraz, po sprawdzeniu czegoś innego :) –

+1

Człowiek, który jest absolutnym śmieci, działa dobrze, jeśli zaimplementuję nietypowe IComparable w klasie nadrzędnej. – CalvinR

3

Próbowałem tego i wpadłem na ten sam błąd. Domyślam się, że ponieważ masz List<Child>, szuka kogoś, kto implementuje IComparable<Child>, a nie IComparable<Parent>.

Po zmianie kolekcji na List<Parent> rzeczy wydają się działać. Ewentualnie, możesz wdrożyć narzędzie Child IComparable<Child> (i może ono po prostu przekazać realizację implementacji Parent).

+0

Tak, niestety, nie zamierzam zmieniać moich zbiorów, aby działać w ten sposób w najbliższym czasie, więc domyślam się, że będę musiał zaimplementować nietypowe IComparable lub po prostu zaimplementować ogólny w każdej z klas, którą chcę posortować . – CalvinR

3

Zgaduję, że ma to coś wspólnego z kwestią kowariancji/kontrawariancji. Dlatego mówię to dlatego, że to nie tak jak mówiłeś:

public class Parent : IComparable<Parent> 
    { 
     public int Age { get; set; } 


     public int CompareTo(Parent other) 
     { 

      return this.Age.CompareTo(other.Age); 
     } 

    } 

    public class Child : Parent 
    { 
     public string Name { get; set; } 
    } 

Jednak, kiedy zmienił rodzica do wdrożenia non generic IComparable i to zrobił, to działało:

public class Parent : IComparable 
    { 
    public int Age { get; set; } 


    public int CompareTo(object other) 
    { 
     Parent p = other as Parent; 
     return this.Age.CompareTo(p.Age); 
    } 

} 

    public class Child : Parent 
    { 
     public string Name { get; set; } 
    } 

kod Testowałem to z:

List<Child> c = new List<Child>(); 
    c.Add(new Child { Age = 10, Name = "Alex" }); 
    c.Add(new Child { Age = 6, Name = "Jack" }); 
    c.Add(new Child { Age = 15, Name = "Bob" }); 

    c.Sort(); 
+0

Tak, znalazłem to samo, miałem tylko nadzieję, że nadal będę mógł używać ogólnej formy Icomparable. – CalvinR

Powiązane problemy