C#为什么这里不需要明确演员?

时间:2018-04-01 11:07:41

标签: c# .net casting

如果没有明确的演员,这段代码如何运作?

static void Main()
{
    IList<Dog> dogs = new List<Dog>();
    IEnumerable<Animal> animals = dogs;
}

我在谈论这一行:

IEnumerable<animal> animals = dogs;

你可以在这里看到我能够在没有明确演员的情况下传递变量狗。但这怎么可能呢?为什么编译器允许我这样做?我不应该先这样做演员:

IEnumerable<Animal> animals = (List<Dog>) dogs;

代码将使用显式强制转换而不使用显式强制转换,但我无法理解为什么它允许我在没有显式强制转换的情况下将dog分配给animals引用变量。

4 个答案:

答案 0 :(得分:8)

IEnumerable<T>covariant interface。这意味着,只要存在隐式引用转换身份转换,就会有从IEnumerable<T1>IEnumerable<T2>的隐式身份转换T1T2。有关此术语的详细信息,请参阅documentation on conversions

如果T2T1的基类(直接或间接),或者是T1实现的接口,则最常见的情况。如果T1T2属于同一类型,或者T2dynamic,也会出现这种情况。

在您的情况下,您正在使用IList<Dog>IList<T>实施IEnumerable<T>。这意味着任何IList<Dog>也是IEnumerable<Dog>,因此隐式参考转化为IEnumerable<Animal>

需要注意的一些重要事项:

  • 只有接口和委托类型可以是协变的或逆变的。例如,List<T>不是协变的,也不可能。例如,你不能写:

    // Invalid
    List<Animal> animals = new List<Dog>();
    
  • 所有接口都是协变的或可变的。例如,IList<T>不是协变的,所以这也不是有效的:

    // Invalid
    IList<Animal> animals = new List<Dog>();
    
  • 方差不适用于值类型,因此这不是有效的:

    // Invalid
    IEnumerable<object> objects = new List<int>();
    

只有在安全的情况下才允许通用差异:

  • 协方差依赖于类型参数仅存在于&#34; out&#34;在任何签名中的位置,即值可以来自实现,但永远不会被接受。
  • Contravariance依赖于类型参数仅存在于&#34;输入&#34;在任何签名中的位置,即值可以传递到实现中,但永远不会返回

当签名接受一个本身是逆变的参数时会有点混乱 - 即使参数通常是&#34;输入&#34;这个位置,它的逆转是逆转的。例如:

public interface Covariant<out T>
{
    // This is valid, because T is in an output position here as
    // Action<T> is contravariant in T
    void Method(Action<T> input);
}

请务必阅读链接文档以获取更多信息!

答案 1 :(得分:5)

因为IEnumerable<T>接口是Covariant。更多信息: https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance

答案 2 :(得分:0)

因为IList< T>继承自IEnumerable<T>。而且我猜你的Dog类也继承自Animal。分配给父类时不需要强制转换。

编辑:这是可能的,因为IEnumerable类是covariant

答案 3 :(得分:-1)

虽然您没有显示,但我认为DogAnimal的子类型。

您始终可以将子类型分配给其父类的实例。

所以List <Dog>可以包含所有类型的狗,因此,如果您有Poodle的课程,继承自Dog,您可以将其放入狗的列表中。

因此IEumerable<Animal>可以包含DogCatPoodle个实例。

在这种情况下,它恰好只包含DogDog的子类。

但你不能这样做:

var animals=new List <Animal>();

Ienumerable<Dog> dogs= animals;

即使您只将Dog个实例插入动物身上。