在C#中,是否可以投射列表<;儿童>;列出<;家长>;?

在C#中,是否可以投射列表<;儿童>;列出<;家长>;?,c#,inheritance,casting,C#,Inheritance,Casting,我想这样做: List<Child> childList = new List<Child>(); ... List<Parent> parentList = childList; List childList=newlist(); ... List parentList=childList; 然而,因为parentList是一个孩子的祖先列表,而不是直接的祖先列表,所以我无法做到这一点。是否有解决方法(除了单独添加每个元素)?使用LINQ: List&l

我想这样做:

List<Child> childList = new List<Child>();
...
List<Parent> parentList = childList;
List childList=newlist();
...
List parentList=childList;
然而,因为parentList是一个孩子的祖先列表,而不是直接的祖先列表,所以我无法做到这一点。是否有解决方法(除了单独添加每个元素)?

使用LINQ:

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

不允许直接强制转换,因为没有办法使其类型安全。如果你有一张长颈鹿的名单,你把它放到一张动物名单上,你就可以把一只老虎放到长颈鹿名单上!编译器不会阻止你,因为当然老虎可能会进入动物列表。编译器唯一能阻止您的地方就是不安全的转换

在C#4中,我们将支持使用引用类型参数化的安全接口和委托类型的协变和逆变。详情请参见此处:


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

List parentList=childList.Cast().ToList();

是的,你可以这样做

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

早在2009年,Eric取笑我们说C#4中的情况会发生变化。那么,我们今天的处境如何

我的答案中使用的类可以在底部找到。为了便于理解,我们将使用
哺乳动物
类作为“家长”,将
类作为“孩子”。猫和狗都是哺乳动物,但猫不是狗,狗也不是猫

这仍然是不合法的,不可能:

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

List<Mammal> mammals = cats;
我们不能允许那样!记住,
哺乳动物
只是对
的引用
Dog
不是从
Cat
派生出来的,也不应该出现在
Cat
对象列表中

,几个泛型接口具有使用C#4中引入的泛型修饰符关键字声明的协变类型参数。在这些接口中,当然是由
List
实现的

这意味着我们现在可以将
列表
转换为
IEnumerable


类别定义:

public abstract class Mammal { }

public class Cat: Mammal { }

public class Dog : Mammal { }

请注意,这将创建一个
childList
的副本,与@Andre Pena.List parentList=childList.OfType().ToList()不使用LINQ版本完全相同;同样有效,并且在您对起始列表的内容不太确定的情况下更可取。如果子级继承自父级,则您可以100%确定强制转换仍然有效。lextm:不适用于列表<代码>列表s既不是协变的,也不是逆变的。@recursive true,因此您可以使用父对象的新列表进行迭代等。但是列表是一个新对象,而不是对原始对象的引用,因此如果您删除其中一个元素,原始列表将不会被修改。例如,它不是完全重复的,但是这里有一个非常类似的问题:更糟糕的是,如果编译器允许你这么做,你的列表会比预期的小,因为老虎会吃掉一些长颈鹿。如果“parent”的类型参数是一个接口,会有什么变化吗?似乎协变收集接口解决了OP的原始问题。++对于唯一找到问题症结的接口:只读接口
IEnumerable<Mammal> mammalsEnumerable = cats;
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);
}
public abstract class Mammal { }

public class Cat: Mammal { }

public class Dog : Mammal { }