18

我想知道为什么在编译时检查 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 将抛出异常。”

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

4

2 回答 2

22
  • Upcasts can be checked at compile time - the type system guarantees that the cast succeeds.
  • Downcasts cannot (in general) be checked at compile time, so they are always checked at runtime.
  • Unrelated types cannot be cast to each other.

The compiler considers only the static types. The runtime checks the dynamic (runtime) type. Looking at your examples:

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

The static type of x is Other. This is unrelated to Derived so the cast fails at compile time.

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

The static type of x is now Base. Something of type Base might have dynamic type Derived, so this is a downcast. In general the compiler can't know from the static type of x if it the runtime type is Base, Derived, of some other subclass of Base. So the decision of whether the cast is allowed is left to the runtime.

于 2010-12-21T13:08:55.293 回答
2

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

您的示例很简单 - 您创建一个新类并立即进行转换。但是如果你Base从其他地方得到,例如,某个方法调用呢?编译器只是无法“猜测”您的方法将返回什么,因此不会抛出错误。

当您进行强制转换时,编译器会发现实际上Other不可能存在并抛出异常。OtherDerived

于 2010-12-21T13:16:58.600 回答