将List <baseclass>复制到List <derivedclass> </derivedclass> </baseclass>

时间:2009-02-05 15:49:24

标签: c# .net

给出以下类定义:

public class BaseClass
{
    public string SomeProp1 { get; set; }
}

public class DerivedClass : BaseClass
{
    public string SomeProp2 { get; set; }
}

如何获取List<BaseClass>并将其转换为List<DerivedClass>

在我的真实场景中BaseClass有一大堆属性,我不想一个一个地复制(然后记得在添加其他属性时保持)。

将参数化构造函数添加到BaseClass不是一个选项,因为此类由WCF服务引用定义。

6 个答案:

答案 0 :(得分:22)

List<DerivedClass> result = 
    listBaseClass.ConvertAll(instance => (DerivedClass)instance);

实际上当你需要根据原始对象创建新对象时,ConvertAll是好的,当你需要施放时你可以使用以下

List<DerivedClass> result = 
    listBaseClass.Cast<DerivedClass>().ToList();

如果不是列表中的所有项目都可以转换为DerivedClass,则使用OfType代替

List<DerivedClass> result =
    listBaseClass.OfType<DerivedClass>().ToList();

答案 1 :(得分:17)

您无法转换实际对象,但可以轻松创建包含已转换内容的新列表:

List<BaseClass> baseList = new List<BaseClass>(...);
// Fill it here...

List<DerivedClass> derivedList = baseList.ConvertAll(b => (DerivedClass) b);

或者如果你没有使用C#3:

List<DerivedClass> derivedList = baseList.ConvertAll<DerivedClass>(delegate
    (BaseClass b) { return (DerivedClass) b; };

这假设原始列表实际上已经充满了DerivedClass的实例。如果不是这样,请更改委托以基于给定的BaseClass创建适当的DerivedClass实例。

编辑:我不确定为什么我不发布LINQ解决方案:

List<DerivedClass> derivedList = baseList.Cast<DerivedClass>().ToList();

答案 2 :(得分:3)

(从here重复)

首先 - 请注意,可以向WCF类添加构造函数(和其他代码) - 您只需要在分部类中执行它(并保留生成的代码)。

听起来需要更改列表中项目的类型 - 所以我们不能只是强制转换。反思是一种选择,但速度很慢。由于您使用的是3.5,我们可以写一个Expression来为我们提高效率......沿these lines,但也使用第二类:

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

答案 3 :(得分:2)

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

}

此代码不仅会转换,还会包含派生类的实例,并排除任何非派生类。

答案 4 :(得分:2)

正如其他人所建议的那样,如果您有一个List<BaseClass>的实例,则可以使用List<DerivedClass>的{​​{1}}方法将其转换为ConvertAll

更一般地说,如果你有任何实现List(没有IEnumerable<T>方法)的东西,你可以使用Linq的ConvertAll做同样的事情:

Cast

如果您需要IEnumerable<DerivedClass> result = listBaseClass.Cast<DerivedClass>(); 而不是List,则可以在结尾处拨打IEnumerable

正如乔恩所说,所有这些都假设ToList()中的所有条目实际上都是listBaseClass类型。

答案 5 :(得分:0)

记录一下,如果有一个带有参数的构造函数,则需要显式实例化列表中的每个项目。

使用OP示例:

public class BaseClass
{
    public BaseClass (string param1)
    {
         Param1 = param1;
    }
    public string SomeProp1 { get; set; }
    public string Param1 { get; private set; }
}

public class DerivedClass : BaseClass
{
    public DerivedClass (string param1) : base(param1){}
    public string SomeProp2 { get; set; }
}

在这种情况下,代码行应类似于:

List<DerivedClass> result = listBaseClass.ConvertAll(l=> new DerivedClass(l.Param1));