2009-02-02 10 views
7

Bien, entonces tengo un escenario similar al siguiente código, tengo una clase principal que implementa IComparable y una clase secundaria.Tengo un problema con IComparable y el método de ordenación de colecciones

class Parent : IComparable<Parent> 
class Child : Parent 

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

Ahora lo anterior funciona bien, puedo comparar dos de los objetos secundarios entre sí ningún problema

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

lo anterior falla, aunque con una excepción InvalidOperationException. ¿Puede alguien explicar por qué este tipo no funciona cuando la clase hija implementa la interfaz IComparable o, al menos, me parece que sí?

Bueno aquí es mi aplicación CompareTo para mi clase padre real

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

Su muestra dice "nueva lista de ()", que supongo es un error tipográfico ... ¿cuál es el tipo genérico real en la lista que está creando? –

+0

Oh lo siento, sí, fue un error tipográfico, tuve la lista l = new List (); Creo que es bastante obvio qué lista de tipos genéricos estaba creando. – CalvinR

+0

¿Podemos ver el código de su implementación IComparable? –

Respuesta

6

Su tipo implementa IComparable<Parent> en lugar de IComparable<Child>. Como dice el MSDN docs for Sort, lanzará InvalidOperationException si "el comparador predeterminado Comparer (T) .Default no puede encontrar una implementación de la interfaz genérica IComparable (T) o la interfaz IComparable para el tipo T." Y de hecho no puede, donde T es Niño. Si intentas convertirlo en List<Parent>, es posible que encuentres que está bien.

EDITAR: Alternativamente (y preferiblemente, IMO) implementar IComparable<Child>. Por el momento, no está nada claro que un niño pueda ser comparado sensiblemente con otro niño. Implementando IComparable<Child> - incluso si esa implementación solo difiere a la implementación base - anuncia la comparabilidad.

+0

No, mi comparación funciona bien, simplemente estoy usando la función de comparación de una variable de miembro de cadena que está almacenada en la clase principal. – CalvinR

+0

Se ha cambiado la respuesta completamente ahora, habiendo revisado algo más :) –

+1

Hombre que es basura absoluta, funciona bien si implemento el IComparable no genérico en la clase principal. – CalvinR

3

Lo intenté y me encontré con el mismo error. Supongo que porque tienes un List<Child> está buscando a alguien que implemente IComparable<Child>, no IComparable<Parent>.

Si cambia la colección a List<Parent>, las cosas parecen funcionar. Alternativamente, haga que Child implemente IComparable<Child> (y solo puede delegar en la implementación de Parent).

+0

Sí, desafortunadamente, no voy a cambiar mis colecciones para que funcionen de esa manera, así que supongo que tendré que implementar el IComparable no genérico o simplemente implementar el genérico en cada una de las clases que quiero ordenar . – CalvinR

3

Supongo que tiene algo que ver con las cosas de covarianza/contravarianza. La razón por la que digo esto es porque esto no funciona como usted ha dicho:

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

Sin embargo, cuando cambié los padres para poner en práctica el IComparable no genérico y lo hizo, funcionó:

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

Código Probé con:

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

Sí, encontré lo mismo, solo esperaba poder seguir usando la forma genérica de Icomparable. – CalvinR

Cuestiones relacionadas