c# - 类型协方差运行时错误

标签 c# covariance

C# 6.0 in a Nutshell by Joseph Albahari and Ben Albahari (O’Reilly).

Copyright 2016 Joseph Albahari and Ben Albahari, 978-1-491-92706-9.

第 123-124 页关于类型协变的陈述:

Arrays, for historical reasons, array types support covariance. This means that B[] can be cast to A[] if B subclasses A (and both are reference types).

For example:

Bear[] bears = new Bear[3]; 
Animal[] animals = bears; // OK

The downside of this reusability is that element assignments can fail at runtime:

animals[0] = new Camel(); // Runtime error

这种错误背后的原因是什么? 如果将 Bear 的实例分配给 Animal 的实例,将抛出运行时错误?我不明白为什么它应该(通过允许这样的分配,编译器需要负责声明“好吧,我会让你用这个对象做动物可以做的一切。”因为 Bear 是一种动物,这会导致没有任何问题。

我创建了自己的场景来测试以上内容:

public class X
{
    public int Num { get; set; }

    public void Method_1()
    {
        Console.WriteLine("X");
    }

    public virtual void Method_2()
    {
        Console.WriteLine(Num);
    }
}

public class Y : X
{
    public Y()
    {
        Num = 1000;
    }
}

X[] arrayX = new X[] { new X { Num = 1000 }, new X { Num = 999 }, new X { Num = 51762 } };
Y[] arrayY = new Y[] { new Y { Num = 5 }, new Y { Num = 6 }, new Y { Num = 7 } };

X x = new X { Num = 1000 };
Y y = new Y { Num = 50 };

x = y;

arrayX = arrayY;

arrayX[2] = new Y { Num = 1 };

// will print 5,6,1 - no runtime errors faced
foreach (var e in arrayX)
    Console.WriteLine(e.Num);

我相信上面的代码片段模仿了书中的示例 - 但对于我的代码片段,没有运行时错误。

我错过了什么?如书中所述,animals[0] = new Camel(); 应该如何引发运行时错误?

最佳答案

What is the reason behind such error?

因为它试图将 Camel 存储到运行时类型为 Bear[] 的数组中。 Bear[] 类型的数组只能存储对Bear 实例或子类的引用。 Animal[] 的编译时类型只表示它可能能够存储一个Camel 引用,并且你得到的任何引用 < em>out 数组肯定是 Animal 实例或子类。

你的例子是不同的。当我们删除所有属性等(不相关的)时,您将获得:

X[] arrayX = new Y[3];
arrayX[2] = new Y();

没关系 - 将对 Y 对象的引用存储在执行时类型为 Y[] 的数组中。没问题。

要演示与书中相同的问题,您需要第三堂课:

class Z : X {}

X[] arrayX = new Z[3];
arrayX[2] = new Y(); // Bang - can't store a Y reference in a Z[]

关于c# - 类型协方差运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38569201/

相关文章:

c# - 协方差和向上转型之间的区别

c# - 为什么 ReadOnlyCollection 不允许协方差?

C++ 模板协变

.net - Entity Framework : ObjectSet and its (generics) variance

c# - 想要使用 C# 中的编码获取字符串数组作为 C 函数的输出

c# - 将此 JSON 制作为一个类

c# - 如何确定 FFmpeg 进程何时完成

c# - 在 .net 4.5 中使用 Async API 的示例串行端口通信代码?

c# - 递归方法比交互式方法慢10倍

c# - 为什么以下在委托(delegate)中使用协方差的示例无法编译?