System.Int32包含...另一个System.Int32

zne*_*eak 14 clr primitive-types

我用反射检查内容,System.Int32发现它包含另一个System.Int32.

System.Int32 m_value;
Run Code Online (Sandbox Code Playgroud)

我不明白这是怎么回事.

int实际上是你所拥有的"后退整数":如果你int打算并使用反射来改变其m_value字段的值,你可以有效地改变整数的值:

object testInt = 4;
Console.WriteLine(testInt); // yields 4

typeof(System.Int32)
    .GetField("m_value", BindingFlags.NonPublic | BindingFlags.Instance)
    .SetValue(testInt, 5);
Console.WriteLine(testInt); // yields 5
Run Code Online (Sandbox Code Playgroud)

这个奇点背后必须有一个理性的解释.值类型如何包含自身?CLR用它来制作它有什么神奇之处?

Han*_*ant 3

如前所述,32 位整数可以有两种形式。内存或 CPU 寄存器(不仅仅是堆栈)中任意位置的四个字节,快速版本。并且它可以嵌入到 System.Object(盒装版本)中。System.Int32 的声明与后者兼容。装箱后,它具有典型的对象标头,后跟存储值的 4 个字节。这 4 个字节精确映射到 m_value 成员。也许您明白为什么这里没有冲突:m_value始终是快速的非装箱版本。因为不存在装箱整数这样的东西。

语言编译器和 JIT 编译器都敏锐地意识到 Int32 的属性。编译器负责决定何时需要对整数进行装箱和拆箱,它会生成相应的 IL 指令来执行此操作。并且它知道哪些 IL 指令可用,允许在不先装箱的情况下对整数进行操作。从 System.Int32 实现的方法中可以明显看出,它没有覆盖例如operator==()。这是由 CEQ 操作码完成的。但它确实有一个对 Equals() 的重写,需要在整数装箱时重写 Object.Equals() 方法。您的编译器需要具有同样的意识。