C# 将 List<BaseClass> 复制到 List<DerivedClass>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/516463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Copying a List<BaseClass> to List<DerivedClass>
提问by Richard Ev
Given the following class definitions:
鉴于以下类定义:
public class BaseClass
{
public string SomeProp1 { get; set; }
}
public class DerivedClass : BaseClass
{
public string SomeProp2 { get; set; }
}
How can I take a List<BaseClass>
and convert it to a List<DerivedClass>
?
我怎样才能把 aList<BaseClass>
转换成 a List<DerivedClass>
?
In my real-world scenario BaseClass
has a whole bunch of properties that I don't want to have to copy over one-by-one (and then remember to maintain if an additional property gets added).
在我的实际场景中,BaseClass
有一大堆属性,我不想一个一个地复制(如果添加了额外的属性,请记住要维护)。
Adding a parameterised constructor to BaseClass
is not an option as this class is defined by a WCF service reference.
添加参数化构造函数BaseClass
不是一个选项,因为此类是由 WCF 服务引用定义的。
采纳答案by Peter Morris
List<DerivedClass> result =
listBaseClass.ConvertAll(instance => (DerivedClass)instance);
Actually ConvertAll is good when you need to create new objects based on the original, when you just need to cast you can use the following
实际上 ConvertAll 在需要基于原始对象创建新对象时很好,当您只需要强制转换时可以使用以下内容
List<DerivedClass> result =
listBaseClass.Cast<DerivedClass>().ToList();
If not all of the items in your list can be cast to DerivedClass then use OfType instead
如果不是您列表中的所有项目都可以转换为 DerivedClass,那么请改用 OfType
List<DerivedClass> result =
listBaseClass.OfType<DerivedClass>().ToList();
回答by Jon Skeet
You can't convert the actual object, but it's easy to create a new list with the converted contents:
您无法转换实际对象,但使用转换后的内容创建新列表很容易:
List<BaseClass> baseList = new List<BaseClass>(...);
// Fill it here...
List<DerivedClass> derivedList = baseList.ConvertAll(b => (DerivedClass) b);
Or if you're not using C# 3:
或者,如果您没有使用 C# 3:
List<DerivedClass> derivedList = baseList.ConvertAll<DerivedClass>(delegate
(BaseClass b) { return (DerivedClass) b; };
This assumes that the original list was actually full of instances of DerivedClass. If that's not the case, change the delegate to create an appropriate instance of DerivedClass based on the given BaseClass.
这假设原始列表实际上充满了 DerivedClass 的实例。如果不是这种情况,请更改委托以基于给定的 BaseClass 创建适当的 DerivedClass 实例。
EDIT: I'm not sure why I didn't just post a LINQ solution:
编辑:我不知道为什么我不只是发布一个 LINQ 解决方案:
List<DerivedClass> derivedList = baseList.Cast<DerivedClass>().ToList();
回答by Marc Gravell
(repeated from here)
(从这里重复)
First - note that you canadd constructors (and other code) to WCF classes - you just need to do it in a partial class (and leave the generated code alone).
首先 - 请注意,您可以向 WCF 类添加构造函数(和其他代码) - 您只需要在部分类中执行此操作(并保留生成的代码)。
It sounds like the typeof the items in the list need to be changed - so we can't just cast. Reflection is an option, but is slow. Since you are using 3.5, we can perhaps write an Expression
to do it for us more efficiently... along these lines, but using the second class too:
听起来列表中项目的类型需要更改 - 所以我们不能只是强制转换。反射是一种选择,但速度很慢。由于您使用的是 3.5,我们也许可以编写一个Expression
更有效地为我们做这件事......沿着这些线,但也使用第二个类:
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);
}
}
}
回答by Peter Morris
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; }
}
}
This code will not only convert, but also only include instances that ARE the derived class and exclude any that are not.
这段代码不仅会转换,而且只会包含派生类的实例,并排除任何不是派生类的实例。
回答by AwesomeTown
As others have suggested, if you have an instance of a List<BaseClass>
you can convert it to a List<DerivedClass>
using the ConvertAll
method of List
.
正如其他人所建议的,如果你有一个实例List<BaseClass>
,你可以将其转换为List<DerivedClass>
使用ConvertAll
的方法List
。
More generally, if you have anything that implements IEnumerable<T>
(which doesn't have a ConvertAll
method) you can use Linq's Cast
to do the same thing:
更一般地说,如果您有任何实现IEnumerable<T>
(没有ConvertAll
方法),您可以使用 LinqCast
来做同样的事情:
IEnumerable<DerivedClass> result = listBaseClass.Cast<DerivedClass>();
If you need an a List
back instead of an IEnumerable
, you can just tack a call to ToList()
on the end.
如果你需要一个List
back 而不是IEnumerable
,你可以ToList()
在最后加上一个电话。
As Jon said, though, that's all assuming that all of the entries in listBaseClass
are actually of type DerivedClass
.
不过,正如 Jon 所说,这一切都是假设 中的所有条目listBaseClass
实际上都是 type DerivedClass
。
回答by ehh
Just for the record, in case there is a constructor with parameters, you need to explicitly instantiate each item in the list.
只是为了记录,如果有带参数的构造函数,您需要显式实例化列表中的每个项目。
Using OP example:
使用 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; }
}
In this case, the line of code should be something like:
在这种情况下,代码行应该是这样的:
List<DerivedClass> result = listBaseClass.ConvertAll(l=> new DerivedClass(l.Param1));