2009-03-26 15 views
19

Estoy seguro de que esta pregunta aborda algo que se habría planteado en una pregunta anterior, pero no pude encontrarla.Conversión de una lista de tipo base en una lista de tipo heredado

Hay un método en una clase C# que toma como parámetro una lista genérica de una clase base. Necesito pasar una lista de una clase heredada y no sé exactamente cómo hacer esto. Estoy recibiendo un error en mis intentos. A continuación se muestra el código de muestra para ilustrar esto:

public class A 
{ 
    public static void MethodC(List<A>) 
    { 
     // Do Something here with the list 
    } 
} 
public Class B : A 
{ 
    // B inherits from A, A is the Base Class 
} 

// Code utilizing the above method 
List<B> listOfB = new List<B>(); 
A.MethodC((List<A>) listOfB); // Error: this does not work 
A.MethodC(listOfB.ToList<typeof(A)>()); // Error: this does not work 
A.MethodC(listOfB.ConvertAll<A>(typeof(A))); // Error: this does not work 
// how can I accomplish this? It should be possible I would think 

Nota: Aquí está mi Método de trabajo final como referencia. Obtuve una solución aún mejor para mi problema, pero técnicamente no fue una respuesta a la pregunta, ya que mi pregunta fue formulada de manera incorrecta.

public static DataTable 
    ObjectCollectionToDataTable<GLIST> 
     (List<GLIST> ObjectCollection) where GLIST 
       : BaseBusinessObject 
     { 
      DataTable ret = null; 

      if (ObjectCollection != null) 
      { 
       foreach (var b in ObjectCollection) 
       { 

        DataTable dt = b.ToDataTable(); 
        if (ret == null) 
         ret = dt.Clone(); 
        if (dt.Rows.Count > 0) 
         ret.Rows.Add(dt.Rows[0].ItemArray); 
       } 
      } 

      return ret; 
     } 
+0

Esa es la misma respuesta que te di ... –

+0

¡Y técnicamente es la respuesta a lo que originalmente pediste, también! :) –

Respuesta

29

Si tiene LINQ disponibles que puede hacer

var ListOfA = ListOfB.Cast<A>().ToList(); 
+0

No creo que tenga linq, pero funcionó de todos modos. muchas gracias por su respuesta rápida. – stephenbayer

+0

Posible problema: ¿necesita MethodC modificar la lista para que esos cambios sean visibles fuera de MethodC? –

+0

¡Me alegro de que funcionó!La única razón por la que creo que tiene los métodos de extensión LINQ disponibles fue el uso de ToList en su ejemplo. –

9

No puede hacer eso. Para entender por qué no está permitido, imagínese lo que sucedería si se llamara Add en un List<Derived> después de haber sido lanzado a List<Base>.

Además, las respuestas que implican que C# 4.0 serán diferentes son incorrectas. La lista nunca se modificará para permitirte hacer esto. Solo IEnumerable lo hará, porque no permite agregar elementos a la colección.

Actualización: La razón por la que funciona en la solución que ha elegido es porque ya no está pasando la misma lista. Está creando una lista completamente nueva que es una copia del original. Es por eso que pregunté sobre la modificación de la lista; si MethodC realiza cambios en el número de elementos en la lista, esos cambios se realizarían en una copia, no en la lista original.

creo que la solución ideal para usted es la siguiente:

public abstract class A 
{ 
    public void MethodC<TItem>(List<TItem> list) where TItem : A 
    { 
     foreach (var item in list) 
      item.CanBeCalled(); 
    } 

    public abstract void CanBeCalled(); 
} 

public class B : A 
{ 
    public override void CanBeCalled() 
    { 
     Console.WriteLine("Calling into B"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<B> listOfB = new List<B>(); 

     A a = new B(); 

     a.MethodC(listOfB); 
    } 
} 

Aviso cómo, con esta solución, se puede pasar un List<B> directamente a MethodC sin necesidad de hacer que la conversión raro en él por primera vez. Entonces no hay copia innecesaria.

La razón de esto funciona es porque hemos dicho MethodC para aceptar una lista de todo lo que se deriva de A, en lugar de insistir en que debe ser una lista de A.

+0

No creo que eso sea cierto, funciona bien. Mi llamada de método funciona en bucles a través de la colección y actúa sobre métodos y propiedades abstractos (anulación). Utilicé el código anterior en una respuesta anterior, y funciona muy bien. el proyecto es .NET 2.0 con CSC.exe (C#) 3.0 como el compilador. – stephenbayer

+0

Ver la actualización anterior. –

+0

Supongo que tienes dificultades para hacer que esto funcione. :) –

3

Aquí hay una respuesta que excluirá cualquier objeto en su lista del tipo incorrecto. Esta es una manera mucho más seguro en mi opinión:

List<A> ListOfA = ListOfB.OfType<A>().ToList(); 

El método OfType excluirá elementos de la clase equivocada derivada en tanto que la moldeada generará un error.

Cuestiones relacionadas