代码之家  ›  专栏  ›  技术社区  ›  Richard Ev

将list<baseclass>复制到list<derivedclass>

  •  21
  • Richard Ev  · 技术社区  · 16 年前

    给定以下类定义:

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

    我怎么能吃 List<BaseClass> 并将其转换为 List<DerivedClass> ?

    在我的真实世界里 BaseClass 有一大堆属性,我不想一个接一个地复制它们(然后记住,如果添加了其他属性,就要维护它们)。

    向添加参数化构造函数 基底玻璃 不是选项,因为此类是由WCF服务引用定义的。

    6 回复  |  直到 6 年前
        1
  •  22
  •   Peter Morris    7 年前
    List<DerivedClass> result = 
        listBaseClass.ConvertAll(instance => (DerivedClass)instance);
    

    实际上,当需要基于原始对象创建新对象时,convertall很好,当只需要强制转换时,可以使用以下内容

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

    如果不是列表中的所有项都可以强制转换为派生类,则改用类型

    List<DerivedClass> result =
        listBaseClass.OfType<DerivedClass>().ToList();
    
        2
  •  17
  •   Jon Skeet    12 年前

    无法转换实际对象,但很容易创建包含转换内容的新列表:

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

    这假定原始列表实际上包含派生类的实例。如果不是这样,请更改委托,以基于给定的基类创建派生类的适当实例。

    编辑:我不知道为什么我不发布LINQ解决方案:

    List<DerivedClass> derivedList = baseList.Cast<DerivedClass>().ToList();
    
        3
  •  3
  •   Community CDub    8 年前

    (重复) 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);
            }
        }
    }
    
        4
  •  2
  •   Peter Morris    16 年前
    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; }
        }
    
    }
    

    此代码不仅将转换,而且还将包括派生类的实例,并排除不属于派生类的实例。

        5
  •  2
  •   AwesomeTown    16 年前

    正如其他人所建议的,如果您有一个 List<BaseClass> 你可以把它转换成 List<DerivedClass> 使用 ConvertAll 方法 List .

    更一般地说,如果您有任何实现 IEnumerable<T> (没有 收敛的 方法)可以使用LINQ Cast 做同样的事情:

    IEnumerable<DerivedClass> result = listBaseClass.Cast<DerivedClass>();
    

    如果你需要A 返回而不是 IEnumerable ,您只需在 ToList() 最后。

    不过,正如乔恩所说,这都是假设 listBaseClass 实际上是类型 DerivedClass .

        6
  •  0
  •   ehh    6 年前

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

    使用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));