在 C# 中,是否可以将 List<Child> 转换为 List<Parent>?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1777800/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:44:02  来源:igfitidea点击:

In C#, is it possible to cast a List<Child> to List<Parent>?

c#inheritancecasting

提问by Matthew

I want to do something like this:

我想做这样的事情:

List<Child> childList = new List<Child>();
...
List<Parent> parentList = childList;

However, because parentList is a Listof Child's ancestor, rather than a direct ancestor, I am unable to do this. Is there a workaround (other than adding each element individually)?

但是,由于 parentList 是Child 的祖先列表,而不是直接祖先,因此我无法执行此操作。是否有解决方法(除了单独添加每个元素)?

采纳答案by Eric Lippert

Casting directly is not allowed because there's no way to make it typesafe. If you have a list of giraffes, and you cast it to a list of animals, you could then put a tiger into a list of giraffes! The compiler wouldn't stop you, because of course a tiger may go into a list of animals. The only place the compiler can stop you is at the unsafe conversion.

不允许直接强制转换,因为无法使其类型安全。如果您有一个长颈鹿列表,并且将其转换为动物列表,那么您可以将老虎放入长颈鹿列表中!编译器不会阻止您,因为当然老虎可能会进入动物列表。编译器可以阻止您的唯一地方是不安全的转换。

In C# 4 we'll be supporting covariance and contravariance of SAFE interfaces and delegate types that are parameterized with reference types. See here for details:

在 C# 4 中,我们将支持使用引用类型参数化的 SAFE 接口和委托类型的协变和逆变。详情请看这里:

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

回答by recursive

Using LINQ:

使用 LINQ:

List<Parent> parentList = childList.Cast<Parent>().ToList();

Documentation for Cast<>()

文档 Cast<>()

回答by Md Shoaib Alam

You can do this by using a Linq approach of the apply extension method, i.e.:

您可以通过使用应用扩展方法的 Linq 方法来做到这一点,即:

List<Parent> parentList = childList.Cast<Parent>().ToList();

回答by caras

yes, you can do it like

是的,你可以这样做

var result = List.And(x => x.Parent.All(b => b.ParentId == value));

回答by Stephen Kennedy

Back in 2009 Eric teased us that things would change in C# 4. So where do we stand today?

早在 2009 年,Eric 就取笑我们说 C# 4 会发生变化。那么我们今天的立场是什么?

The classes used in my answer can be found at the bottom. To make this easier to follow, we will use a Mammalclass as "parent", and Catand Dogclasses as "children". Cats and dogs are both mammals, but a cat is not a dog and a dog is not a cat.

我的答案中使用的类可以在底部找到。为了更容易理解,我们将使用一个Mammal类作为“父”,Cat并将Dog类用作“子”。猫和狗都是哺乳动物,但猫不是狗,狗也不是猫。

This still isn't legal, and can't be:

这仍然不合法,并且不能:

List<Cat> cats = new List<Cat>();

List<Mammal> mammals = cats;

Why not? Cats are mammals, so why can't we assign a list of cats to a List<Mammal>?

为什么不?猫是哺乳动物,那么为什么我们不能将猫的列表分配给 a List<Mammal>

Because, if we were allowed to store a reference to a List<Cat>in a List<Mammal>variable we would then be able to compile the following code to add a dog to a list of cats:

因为,如果允许我们List<Cat>List<Mammal>变量中存储对 a 的引用,那么我们就可以编译以下代码将一只狗添加到猫的列表中:

mammals.Add(new Dog());

We mustn't allow that! Remember, mammalsis just a reference to cats. Dogdoes not descend from Catand has no business being in a list of Catobjects.

我们不能允许!请记住,mammals只是对cats. DogCat属于Cat对象列表并且与对象列表无关。

Starting with .NET Framework 4, several generic interfaces have covariant type parameters declared with the outGeneric Modifier keyword introduced in C# 4. Amongst these interfaces is IEnumerable<T>which of course is implemented by List<T>.

从 .NET Framework 4 开始,几个泛型接口具有使用outC# 4 中引入的Generic Modifier 关键字声明的协变类型参数。在这些接口IEnumerable<T>中,当然是由List<T>.

That means we cannow cast a List<Cat>to an IEnumerable<Mammal>:

这意味着我们现在可以将 a 转换List<Cat>为 an IEnumerable<Mammal>

IEnumerable<Mammal> mammalsEnumerable = cats;

We can't add a new Dogto mammalsEnumerablebecause IEnumerable<out T>is a "read-only" interface i.e. it has no Add()method, but we cannow use catswherever a IEnumerable<Mammal>can be consumed. For example, we can concatenate mammalsEnumerablewith a List<Dog>to return a new sequence:

我们不能添加一个新的DogmammalsEnumerable,因为IEnumerable<out T>是“只读”的界面,也就是没有Add()方法,但我们可以现在使用cats的地方一个IEnumerable<Mammal>可以食用。例如,我们可以mammalsEnumerable与 a连接List<Dog>以返回一个新序列:

void Main()
{
    List<Cat> cats = new List<Cat> { new Cat() };
    IEnumerable<Mammal> mammalsEnumerable =
        AddDogs(cats); // AddDogs() takes an IEnumerable<Mammal>
    Console.WriteLine(mammalsEnumerable.Count()); // Output: 3. One cat, two dogs.
}

public IEnumerable<Mammal> AddDogs(IEnumerable<Mammal> parentSequence)
{
    List<Dog> dogs = new List<Dog> { new Dog(), new Dog() };
    return parentSequence.Concat(dogs);
}


Class definitions:

类定义:

public abstract class Mammal { }

public class Cat: Mammal { }

public class Dog : Mammal { }