2009-02-02 10 views
7

Okay, so habe ich ein Szenario ähnlich dem folgenden Code, ich habe eine Elternklasse, die IComparable und eine Kindklasse implementiert.Ich habe ein Problem mit IComparable und die Sammlung Sortiermethode

class Parent : IComparable<Parent> 
class Child : Parent 

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

Nun werden die oben funktioniert gut, ich kann zwei des Kindes vergleichen zueinander Objekte kein Problem

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

Die oben zwar mit einer InvalidOperationException ausfällt. Kann jemand bitte erklären, warum diese Art nicht funktioniert, wenn die Kindklasse die IComparable-Schnittstelle implementiert, oder zumindest scheint es mir, dass es tut.

Okay, hier ist meine CompareTo Implementierung für meine eigentliche Elternklasse

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

Ihre Probe sagt „neue Liste ()“, die ich vermute, bin ein Tippfehler ist ... was ist der eigentliche generischen Typ auf der Liste Sie erstellen? –

+0

Oh sorry yeah es war ein Tippfehler, ich hatte Liste l = neue Liste (); Ich denke, es ist ziemlich offensichtlich, welche generische Typenliste ich erstellt habe. – CalvinR

+0

Können wir den Code aus Ihrer IComparable-Implementierung sehen? –

Antwort

6

Ihr Typ implementiert IComparable<Parent> statt IComparable<Child>. Wie die MSDN docs for Sort sagen, wird es InvalidOperationException werfen, wenn "der Standardvergleich Comparer (T) .Default eine Implementierung der IComparable (T) generische Schnittstelle oder der IComparable-Schnittstelle für Typ T nicht finden kann." Und in der Tat kann es nicht, wo T Kind ist. Wenn Sie versuchen, es zu einem List<Parent> machen, können Sie gut finden, dass es in Ordnung ist.

EDIT: Alternativ (und vorzugsweise IMO) implementieren IComparable<Child>. Im Moment ist es überhaupt nicht klar, dass ein Kind vernünftig mit einem anderen Kind verglichen werden kann. Das Implementieren von IComparable<Child> - auch wenn diese Implementierung nur auf die Basisimplementierung verweist - macht die Vergleichbarkeit bekannt.

+0

Nein mein Vergleich funktioniert gut, ich verwende einfach die Vergleichsfunktion einer String-Member-Variable, die in der Elternklasse gespeichert ist. – CalvinR

+0

Geändert Antwort jetzt vollständig, etwas anderes überprüft :) –

+1

Mann, das ist absolut Müll, es funktioniert gut, wenn ich das nicht-generische IComparable in der Elternklasse implementieren. – CalvinR

3

Ich habe dies versucht und lief in den gleichen Fehler. Meine Vermutung ist, dass, weil Sie eine List<Child> haben, es jemanden sucht, der IComparable<Child>, nicht IComparable<Parent> implementiert.

Wenn Sie die Sammlung in List<Parent> ändern, scheinen die Dinge zu funktionieren. Alternativ können Sie Child implementieren IComparable<Child> (und es kann nur an die Implementierung von Parent delegieren).

+0

Ja, leider werde ich meine Sammlungen nicht so ändern, dass sie so bald funktionieren werden, also muss ich einfach das nicht-generische IComparable implementieren oder einfach das generische in jeder der Klassen implementieren, die ich sortieren möchte . – CalvinR

3

Meine Vermutung ist, dass es etwas mit dem Kovarianz/Kontravarianz-Zeug zu tun hat. Der Grund, warum ich sagen, dass liegt daran, dass dies nicht gelingt, wie Sie gesagt haben:

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

Allerdings, wenn ich die Eltern änderte die nicht generische IComparable und tat dies umzusetzen, es funktionierte:

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

Code I getestet mit:

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

Ja, ich habe das gleiche gefunden, ich habe nur gehofft, ich könnte immer noch die generische Form von unvergleichbar verwenden. – CalvinR