编译时和运行时转换c#

时间:2010-12-21 13:05:22

标签: c# .net casting type-systems

我想知道为什么在编译时会检查C#中的某些强制转换,而在其他情况下,责任会转储到CLR上。如上所述都是不正确的,但以不同的方式处理。

class Base { }
class Derived : Base { }
class Other { }

static void Main(string[] args)
{
    Derived d = (Derived)new Base();     //Runtime       InvalidCastException
    Derived d = (Derived)new Other();    //Compile-time  Cannot convert type...
}

在阅读“C#深度”的同时,我找到了有关此主题的信息,其中autor说:
  “如果编译器发现该转换实际上不可能工作,它将触发编译错误 - 如果理论上允许但在执行时实际上不正确,则CLR将抛出异常。”

“理论上”是否意味着通过继承层次结构(对象之间的另一个亲和力?)连接,还是编译器的内部业务?

2 个答案:

答案 0 :(得分:22)

  • 可以在编译时检查向上转换 - 类型系统保证转换成功。
  • 在编译时不能(通常)检查Downcast,因此总是在运行时检查它们。
  • 不相关的类型不能互相投射。

编译器仅考虑静态类型。运行时检查动态(运行时)类型。 看看你的例子:

Other x = new Other();
Derived d = (Derived)x; 

x的静态类型为Other。这与Derived无关,因此转换在编译时失败。

Base x = new Base();
Derived d = (Derived)x; 

x的静态类型现在为BaseBase 类型的某些内容可能具有动态类型Derived,因此这是一个向下转发。通常,编译器无法从x的静态类型中了解Base的某些其他子类的运行时类型是DerivedBase。因此决定是否允许强制转换是留给运行时的。

答案 1 :(得分:1)

如果您的变量属于Base类型,理论上可以由Derived构造函数构造,因此实际上是Derived类型的变量。在编译时,编译器不会费心去试图弄清楚在每个特定情况下是否可以进行这种向下转换(将Base类型的变量表示为Derived类型的实体)。

您的样本很简单 - 您创建一个新类并立即投射它。但是,如果你从其他地方获得Base该怎么办?例如,某些方法调用?编译器无法“猜测”您的方法将返回什么,因此不会抛出错误。

当您转换Other时,编译器发现Other实际上不可能Derived并抛出异常。