繁体   English   中英

通用协方差编译时间安全检查

[英]Generic covariance compile time safety checks

为什么原因List<T>未在协变T ,而IEnumerable<T> 上协变T通常是由这样一个例子来说明。

给定以下类别:

public class Fruit
{
}

public class Apple : Fruit
{
}

public class Banana : Fruit
{
}

允许以下内容:

public void Permitted()
{
    IEnumerable<Fruit> bananas = new List<Banana>
    {
        new Banana(),
        new Banana(),
        new Banana(),
    };

    foreach (Fruit banana in bananas)
    {
        // This is all good, because a banana "is a" fruit and
        // we can treat it as such.
    }
}

以下是不允许的:

public void Disallowed()
{
    // Compiler rejects this!
    List<Fruit> bananas = new List<Banana>
    {
        new Banana(),
        new Banana(),
        new Banana(),
    };

    // ...Otherwise we can add an apple to a list containing bananas
    bananas.Add(new Apple());
}

但是,我们仍然可以通过执行以下操作来实现:

public void Loophole()
{
    // Compiler is happy again
    IEnumerable<Fruit> bananas = new List<Banana>
    {
        new Banana(),
        new Banana(),
        new Banana(),
    };

    // ...And now we can add an apple to a list of bananas
    bananas.ToList().Add(new Apple());
}

当然,我们可以这样做:

public void AlsoAllowed()
{
    var fruit = new List<Fruit>();
    fruit.Add(new Apple());
    fruit.Add(new Banana());
}

List<T>协变量不是协变的(据我的理解)是这样做可以使我们向包含派生对象的集合中添加任意基础对象。 也许这是一个过分的简化,但这不是上面的示例正在做的事情吗?

当您执行bananas.ToList().Add(new Apple())bananas.ToList()创建List<Fruit> 这是一个列表类型,可以包含任何类型的水果。 可以将new Apple()添加到该列表中的事实很有意义。

bananas类型为List<Banana> ,这是一个只能包含香蕉的列表类型。 无法将new Apple()添加到此列表,并且您的示例也没有new Apple()添加到此列表。 您的示例将创建一个更宽容的列表,然后添加到列表中,但保留原始列表不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM