0

我有两节课

 public class A
    {
        public A()
        {

        }
    }

    public class B:A
    {
        public B()
        {

        }
    }

Main中的代码如下

    A oa = new B();
    B ob = new A();

这里第 1 行编译成功,而第 2 行显示类型转换错误。为什么会发生这种情况。new B()当和new A()被调用时究竟会发生什么?

4

2 回答 2

7

您已经声明了一个 type 的变量B,然后尝试为其分配一个 type 的值A。您已定义B为一种 of A,但这并不意味着所有A's 都是B's。

可以这样想:

class Animal { }
class Dog : Animal { }
class Cat : Animal { }

你可以Animal rex = new Dog(),因为所有的狗都是动物,但不是Dog fido = new Animal(),因为不是所有的动物都是狗。

于 2010-09-06T12:19:58.587 回答
2

当 new B() 和 new A() 被调用时究竟会发生什么?

  • new A()在堆上构造一个类型的对象A并返回对它的引用。

  • new B()在堆上构造一个类型的对象B并返回对它的引用。

这里第 1 行编译成功,而第 2 行显示类型转换错误。为什么会发生这种情况。

由于是B子类A,类型的引用引用A运行时类型的对象是有效的B。毕竟,B只是一个“特例” A

然而,反之则不成立,因为不是所有A的 s 都可以被认为是Bs。尽管 C# 的安全类型系统严格执行了这一点,即使没有“真正的”不兼容,但这种限制的原因是自然的。例如,想象一下,它B声明了一个 property public int Foo {get; set;}。你会如何期望它的行为:

B ob = new A();
ob.Foo = 5;

这显然是不合逻辑的:引用所指的真实对象没有这样的属性。因此,编译器禁止此类构造。

现在假设您将代码更改为:

B b = (B)new A();

在这里,您告诉编译器创建的对象将在运行时分配给 type 的引用B。这将编译得很好,但由于断言显然是不正确的,所以InvalidCastException会抛出一个运行时。

总而言之,C# 的类型系统(如果您忽略dynamic和一些特殊情况)既是静态的又是安全的:您将无法成功地将具体实例A视为 type B

于 2010-09-06T12:19:05.577 回答