实际铸件在CLR级别如何工作?

在进行向上或向下投射时,幕后真的会发生什么? 我有一个想法,当做某事时:

string myString = "abc"; object myObject = myString; string myStringBack = (string)myObject; 

最后一行中的强制转换只会告诉编译器我们是安全的,我们没有做错任何事。 所以,我认为实际上代码本身不会嵌入任何强制转换代码。 看来我错了:

 .maxstack 1 .locals init ( [0] string myString, [1] object myObject, [2] string myStringBack) L_0000: nop L_0001: ldstr "abc" L_0006: stloc.0 L_0007: ldloc.0 L_0008: stloc.1 L_0009: ldloc.1 L_000a: castclass string L_000f: stloc.2 L_0010: ret 

为什么CLR需要类似castclass string东西?

向下转换有两种可能的实现方式:

  1. 你需要一个castclass something 。 当你到达执行转换类的代码castclass ,CLR会尝试进行转换。 但是,如果我省略了castclass字符串并尝试运行代码,会发生什么?
  2. 您不需要castclass 。 由于所有引用类型都具有类似的内部结构,如果您尝试在Form实例上使用字符串,它将抛出错误用法的exception(因为它检测到Form不是字符串或其任何子类型)。

另外,来自C#4.0的以下statamente是否正确?

 Upcasting and downcasting between compatible reference types performs reference conversions: a new reference is created that points to the same object. 

它真的创造了一个新的参考? 我认为它是相同的引用,只存储在不同类型的变量中。

谢谢

我有一个想法,实际上代码本身不会嵌入任何强制转换代码。

一个有趣的想法。 你怎么想象这个有效?

 try { object x = 123; object y = (string)x; } catch(InvalidCastException ex) { ... } 

如果强制转换不生成代码,则抛出exception的代码在哪里发生

请记住,从较少特定类型到更具体类型的强制转换的主要目的执行运行时类型检查

一旦类型检查通过,那么肯定,没有其他任何事情真的发生。 类型检查前的引用位和类型检查后的位是相同的位; 我们刚刚运行时validation旧位的新用法是否合理。

如果您尝试在Form实例上使用字符串,它将抛出错误用法的exception(因为它检测到Form不是字符串或其任何子类型)。

它在哪里检测到了? 我的意思是, 究竟在哪个指令被检测到? 在castclass指令中 。 这就是castclass指令的用途。

如果我省略了castclass字符串行并尝试运行代码,会发生什么?

类型安全validation程序会拒绝您的程序。 如果你强制CLR运行它而不通过validation,那么它将有未定义的行为。 它可能已经成功,它可能已经失败,它可能已经格式化了您的硬盘。

它真的创造了一个新的参考?

请记住,在实现级别,引用只是一个指针大小的整数。 这是内存管理器可用于跟踪引用数据位置的数字。 它可能是一个指针,它可能是一个句柄,它无关紧要; 它是实现引用的抽象概念的东西。

当你有一个包含12的变量并用12“替换”它的内容时,是刚刚创建的“新”12还是“旧”12? 假设您通过从第一个变量复制来创建第二个变量并将12放入其中。 那是“新”12还是“老”12? 你怎么知道? 这是一个没有区别的差异。 当你创建一个与“旧”引用相同的“新”引用是创建新的东西吗? 问题是一个哲学问题,而不是技术问题。

你对实例的引用感到困惑。 创建新引用 ,而不是新实例。

 object foo = "bar"; string baz = (string)foo; 

字符串"foo"引用被分配给baz变量(但是仍然只有一个字符串实例,只是两个变量都指向单个实例)。 如果不是这种情况,你会有类似“手柄”类型的东西。 如果bazfoo在字面上是相同的参考,那么这..

 foo = "bim"; 

也会使baz等于"bim" (同样,指定非字符串类型会使baz不再指向有效的字符串引用)。

您可以在引用类型中执行强制转换,只要它们位于相同的inheritance层(一个直接或间接地从另一个inheritance)或者存在类型之间的显式转换时。 请注意,与所有其他运算符一样,显式转换不是多态的 – 也就是说,转换必须专门针对其中一个类进行定义 ,而不是在层次结构中的另一个位置。

显式转换(如果存在)将优先考虑,即使所讨论的类型在没有它的情况下兼容。 在显式转换的情况下,您无法保证(事实上,它不太可能)转换/转换的结果将指向与正在转换的对象相同的实例。