2011-06-24 14 views
7

Tengo un problema interesante en el que una clase hereda de una clase que implementa IEnumerable, pero también quiero que la clase implemente IEnumerable para un tipo diferente. Todo funciona, excepto los métodos de extensión IEnumerable, lo que significa que no puedo hacer ningún LINQ a los objetos por defecto sin tener que lanzar primero. ¿Alguien tiene alguna idea además de lanzar constantemente?¿Por qué no puedo usar LINQ to Objects cuando mi clase implementa IEnumerable <T> varias veces?

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace LinqTesting 
{ 
    public class Trucks<T> : Vehicles, IEnumerable<Truck> 
    {  
     public Trucks() 
     {  
      // Does Compile 
      var a = ((IEnumerable<Truck>)this).FirstOrDefault(); 
      // Doesn't Compile, Linq.FirstOrDefault not found 
      var b = this.FirstOrDefault(); 
     }  

     public new IEnumerator<Truck> GetEnumerator() { throw new NotImplementedException(); } 
    }  

    public class Vehicles : IEnumerable<Vehicle> 
    {  
     public IEnumerator<Vehicle> GetEnumerator() { throw new NotImplementedException(); } 
     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new NotImplementedException(); } 
    }  

    public class Vehicle { } 

    public class Truck : Vehicle { } 
}  
+2

¿Su objeto de camión no está heredando dos tipos de IEnumerable? ¿Cómo espera que el compilador descubra qué tipo enumerable desea usar, intente redirigir a la que desea y luego seleccione FirstOrDefault –

Respuesta

6

En realidad se puede, pero no podrá beneficiarse de tipos genéricos inferencia, porque su clase implementa dos IEnumerable<T> de dos tipos diferentes y el compilador no puede saber qué tipo quieres usar

Puede especificar que direclty de, como:

var b = this.FirstOrDefault<Truck>(); 
+0

Esto es realmente lo que me estaba perdiendo. Era confuso porque el intellisense mostraría el método, pero también mostraría el error en la misma línea porque el compilador ya no podría aprovechar la inferencia de tipo genérico. – Daryl

4

La implementación de IEnumerable múltiples veces confunde compilador, que IEnumerable <> Debe tener en cuenta para esto.

IEnumerable<Vehicle> or IEnumerable<Truck>? 

this.FirstOrDefault<Truck>() might compile. 
0

pública nueva IEnumerator GetEnumerator()

Eso new palabra clave en esa línea cueros el método GetEnumerator() heredado de la clase de vehículo. No estoy seguro de que esto funcione, pero tal vez intente con explicit interface implementation.

+0

Usar implementaciones de interfaz explícitas para algunas interfaces e implícito para otras no cambia la resolución del método de extensión. Solo ayuda si está llamando 'GetEnumerator()' directamente, por lo que esto no ayuda. – binki

7

cambiar el código para:

public class Trucks : Vehicles<Truck> 
{  
}  

public class Vehicles<T> : IEnumerable<T> 
    where T : Vehicle 
{  
}  

public class Vehicle { } 

public class Truck : Vehicle { } 
+0

solo unos pocos minutos para ralentizar;) – Clayton

+0

@Clayton - así es la vida ;-) –

+0

lamentablemente no tengo acceso al código de la clase base, pero esa sería la solución correcta. Tendré que ver si puedo hacer ese cambio. ¡Gracias! – Daryl

2

Parece que eres un poco atascado. Aquí hay una sugerencia para reducir su tipeo. Puede crear un método de extensión para algunos de los tipos más comunes de IEnumerable <>.

var a = myList.AsTruckEnumerable().FirstOrDefault(); 

public static partial class Extensions 
{ 
    public static IEnumerable<Truck> AsTruckEnumerable (this IEnumerable<Truck> trucks) 
    { 
    return trucks; 
    } 
} 

public class Trucks<T> : Vehicles, IEnumerable<Truck> 
{  
    public Trucks() 
    {  
     // Does Compile 
     var a = ((IEnumerable<Truck>)this).FirstOrDefault(); 

     // Does compile 
     var b = this.AsTruckEnumerable().FirstOrDefault(); 
     // Doesn't Compile, Linq.FirstOrDefault not found 
     //var b = this.FirstOrDefault(); 
    }  

    public new IEnumerator<Truck> GetEnumerator() { throw new NotImplementedException(); } 
}  
Cuestiones relacionadas