【问题标题】:Compile-time and runtime casting c#编译时和运行时强制转换 c#
【发布时间】:2011-05-28 19:46:41
【问题描述】:

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

“理论上”是指通过继承层次结构连接(对象之间的其他关联?)还是编译器的内部业务?

【问题讨论】:

    标签: c# .net casting type-systems


    【解决方案1】:
    • 可以在编译时检查向上转换 - 类型系统保证转换成功。
    • (通常)无法在编译时检查向下转换,因此始终在运行时检查它们。
    • 不相关的类型不能相互转换。

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

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

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

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

    x 的静态类型现在是BaseBase 类型的东西 可能 具有动态类型 Derived,所以这是一个低调。一般来说,编译器无法从x 的静态类型中知道它的运行时类型是否是BaseDerivedBase 的某个其他子类。因此,是否允许强制转换的决定由运行时决定。

    【讨论】:

    • 所以可以假设编译器也检查隐式/显式转换运算符重载?
    【解决方案2】:

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

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

    当你转换Other 时,编译器会看到Other 实际上不可能是Derived 并抛出异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-25
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多