在 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
In C#, is it possible to cast a List<Child> to List<Parent>?
提问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();
回答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 Mammal
class as "parent", and Cat
and Dog
classes 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, mammals
is just a reference to cats
. Dog
does not descend from Cat
and has no business being in a list of Cat
objects.
我们不能允许!请记住,mammals
只是对cats
. Dog
不Cat
属于Cat
对象列表并且与对象列表无关。
Starting with .NET Framework 4, several generic interfaces have covariant type parameters declared with the out
Generic Modifier keyword introduced in C# 4. Amongst these interfaces is IEnumerable<T>
which of course is implemented by List<T>
.
从 .NET Framework 4 开始,几个泛型接口具有使用out
C# 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 Dog
to mammalsEnumerable
because IEnumerable<out T>
is a "read-only" interface i.e. it has no Add()
method, but we cannow use cats
wherever a IEnumerable<Mammal>
can be consumed. For example, we can concatenate mammalsEnumerable
with a List<Dog>
to return a new sequence:
我们不能添加一个新的Dog
来mammalsEnumerable
,因为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 { }