题
我有两个课
public class A
{
public A()
{
}
}
public class B:A
{
public B()
{
}
}
它的主要代码如下
A oa = new B();
B ob = new A();
在此处,第1行成功编译时,当第2行显示打字错误。为什么会发生这种情况。到底会发生什么 new B()
和 new A()
被打电话?
解决方案
当新的B()和New A()被调用时,到底会发生什么?
new A()
构建类型的对象A
在堆上返回对其的引用。new B()
构建类型的对象B
在堆上返回对其的引用。
在此处,第1行成功编译时,当第2行显示打字错误。为什么会发生这种情况。
自从 B
子类 A
, ,对于类型的引用是有效的 A
引用运行时类型的对象 B
. 。毕竟, B
只是一个“特殊情况” A
.
但是,匡威不是真的,因为不是全部 A
可以考虑 B
s。虽然这是C#严格执行的 安全的 类型系统即使没有“真正的”不相容性,这种限制的原因也是自然的。想象一下,例如 B
宣布财产 public int Foo {get; set;}
。您如何期望这表现:
B ob = new A();
ob.Foo = 5;
这显然是不合逻辑的: 真实的 引用所指的对象没有此类属性。因此,编译器禁止这种结构。
现在想象您将代码更改为:
B b = (B)new A();
在这里,您告诉编译器对象创建的对象将在 运行, ,可分配给类型的参考 B
. 。这会符合良好的汇编,但是由于断言明显不正确,因此运行时间 InvalidCastException
将被扔。
总而言之,C#的类型系统(如果您忽略 dynamic
还有一些特殊情况)是 静止的 和 安全的: :您将无法成功处理具体实例 A
好像是类型 B
.
其他提示
您已经声明了类型的变量 B
, ,然后尝试分配类型的值 A
对此。您已经定义了 B
成为一种 A
, ,但这并不意味着全部 A
是 B
'
这样想:
class Animal { }
class Dog : Animal { }
class Cat : Animal { }
你可以做 Animal rex = new Dog()
, ,因为所有狗都是动物,但不是 Dog fido = new Animal()
, ,因为并非所有动物都是狗。