c# - Copiando una lista<BaseClass> a List<DerivedClass>
.net (5)
Como otros han sugerido, si tiene una instancia de una List<BaseClass>
puede convertirla a una List<DerivedClass>
usando el método ConvertAll
de List
.
De manera más general, si tiene algo que implementa IEnumerable<T>
(que no tiene un método ConvertAll
) puede usar Cast
de Linq para hacer lo mismo:
IEnumerable<DerivedClass> result = listBaseClass.Cast<DerivedClass>();
Si necesita una A en la parte posterior de la List
en lugar de un IEnumerable
, puede simplemente marcar una llamada a ToList()
al final.
Sin embargo, como dijo Jon, eso es todo suponiendo que todas las entradas en listBaseClass
en realidad son del tipo DerivedClass
.
Dadas las siguientes definiciones de clase:
public class BaseClass
{
public string SomeProp1 { get; set; }
}
public class DerivedClass : BaseClass
{
public string SomeProp2 { get; set; }
}
¿Cómo puedo tomar una List<BaseClass>
y convertirla en una List<DerivedClass>
?
En mi escenario del mundo real, BaseClass
tiene un montón de propiedades que no quiero copiar una a una (y luego recordar mantenerlas si se agrega una propiedad adicional).
Agregar un constructor parametrizado a BaseClass
no es una opción ya que esta clase está definida por una referencia de servicio WCF.
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace ConsoleApplication22
{
class Program
{
static void Main(string[] args)
{
List<BaseClass> source = new List<BaseClass>();
source.Add(new DerivedClass { Name = "One" });
source.Add(new BaseClass());
source.Add(new DerivedClass { Name = "Three" });
List<DerivedClass> result =
new List<DerivedClass>(source.OfType<DerivedClass>());
result.ForEach(i => Console.WriteLine(i.Name));
Console.ReadLine();
}
}
public class BaseClass
{
}
public class DerivedClass : BaseClass
{
public string Name { get; set; }
}
}
Este código no solo convertirá, sino que solo incluirá instancias que SON la clase derivada y excluirá las que no lo sean.
No puede convertir el objeto real, pero es fácil crear una nueva lista con los contenidos convertidos:
List<BaseClass> baseList = new List<BaseClass>(...);
// Fill it here...
List<DerivedClass> derivedList = baseList.ConvertAll(b => (DerivedClass) b);
O si no estás usando C # 3:
List<DerivedClass> derivedList = baseList.ConvertAll<DerivedClass>(delegate
(BaseClass b) { return (DerivedClass) b; };
Esto supone que la lista original en realidad estaba llena de instancias de DerivedClass. Si ese no es el caso, cambie el delegado para crear una instancia apropiada de DerivedClass basada en la BaseClass dada.
EDITAR: No estoy seguro de por qué no acaba de publicar una solución LINQ:
List<DerivedClass> derivedList = baseList.Cast<DerivedClass>().ToList();
List<DerivedClass> result =
listBaseClass.ConvertAll(instance => (DerivedClass)instance);
En realidad, ConvertAll es bueno cuando necesitas crear objetos nuevos basados en el original, cuando solo necesitas lanzar puedes usar lo siguiente
List<DerivedClass> result =
listBaseClass.Cast<DerivedClass>();
Si no todos los elementos de tu lista se pueden convertir a DerivedClass, utiliza OfType en su lugar
List<DerivedClass> result =
listBaseClass.OfType<DerivedClass>();
(repetido desde aquí )
En primer lugar, tenga en cuenta que puede agregar constructores (y otro código) a las clases WCF; solo tiene que hacerlo en una clase parcial (y dejar solo el código generado).
Parece que el tipo de los elementos de la lista debe cambiarse, por lo que no podemos simplemente lanzar. La reflexión es una opción, pero es lenta. Como está utilizando 3.5, tal vez podamos escribir una Expression
para hacerlo de manera más eficiente ... en esta línea , pero también con la segunda clase:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
class Foo
{
public int Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
class Bar : Foo {}
static void Main()
{
List<Foo> foos = new List<Foo>();
for (int i = 0; i < 10; i++) foos.Add(new Foo { Value = i });
List<Bar> bars = foos.ConvertAll<Bar>(Clone<Foo, Bar>);
}
public static TTo Clone<TFrom, TTo>(this TFrom obj) where TTo : TFrom, new()
{
return ObjectExtCache<TFrom, TTo>.Convert(obj);
}
static class ObjectExtCache<TFrom, TTo> where TTo : TFrom, new()
{
private static readonly Func<TFrom, TTo> converter;
static ObjectExtCache()
{
ParameterExpression param = Expression.Parameter(typeof(TFrom), "in");
var bindings = from prop in typeof(TFrom).GetProperties()
where prop.CanRead && prop.CanWrite
select (MemberBinding)Expression.Bind(prop,
Expression.Property(param, prop));
converter = Expression.Lambda<Func<TFrom, TTo>>(
Expression.MemberInit(
Expression.New(typeof(TTo)), bindings), param).Compile();
}
public static TTo Convert(TFrom obj)
{
return converter(obj);
}
}
}