【问题标题】:Type casting error and constructor类型转换错误和构造函数
【发布时间】:2010-09-06 12:14:22
【问题描述】:

我有两节课

 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() 被调用时会发生什么?

【问题讨论】:

    标签: c# .net casting static-typing


    【解决方案1】:

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

    这样想:

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

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

    【讨论】:

      【解决方案2】:

      当 new B() 和 new A() 被调用?

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

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

      这里第1行编译成功 而第 2 行显示类型转换 错误。为什么会这样。

      由于BA 的子类,因此A 类型的引用可以引用运行时类型B 的对象。毕竟B只是A的“特例”。

      然而,反之则不然,因为不是所有的As 都可以被认为是Bs。 尽管这由 C# 的 safe 类型系统严格执行,即使没有“真正的”不兼容,但这种限制的原因是自然的。例如,想象一下B 声明了一个属性public int Foo {get; set;}。 您希望它的表现如何:

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

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

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

      B b = (B)new A();

      在这里,您告诉编译器创建的对象将在运行时分配给B 类型的引用。这将编译得很好,但由于断言显然不正确,因此将抛出运行时InvalidCastException

      总而言之,C# 的类型系统(如果您忽略 dynamic 和一些特殊情况)既是 static 又是 safe:您将无法成功处理A 的具体实例,就好像它是 B 类型一样。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-09
        • 2012-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-21
        • 2018-12-04
        • 2016-03-14
        相关资源
        最近更新 更多