在读了一下Int32
C#中的结构后,我意识到int
并且Int32
是同义词.在struct 的源代码中Int32
,有一个internal int m_value
字段.
如果我的知识是正确的,我们分配给int变量的值存储在m_value
(我是否正确?).但我怀疑的是,m_value
当我们给出时,价值是如何存储的int i = 7;
.
我没有在Int32
struct源代码中看到任何隐式运算符,因此可以存储该值m_value
.
谁能帮我这个?
int
在C#中表示与int32
CIL中相同的东西,CIL是一个4字节的原语,通常被视为带符号的数字.(虽然CIL可以在没有强制转换的情况下对其执行无符号操作).
它是最低级别的构建块之一,我们可以继续创建更复杂的结构和类.
但同样,它没有定义任何方法.
System.Int32
同时看起来非常像一个包装int
/ int32
并提供一些方法的结构.
让我们考虑一下; 让我们思考一个没有int
别名的世界会是什么样子System.Int32
:
在这个假设的情况下,System.Int32
如果我们将它视为特殊的"盒装int"类型,我们将被允许使用提供的方法,System.Int32
从int
我们需要时创建一个,并int
在需要时再次提取返回.
因此,如果没有别名,(3).CompareTo(2)
我们必须这样做:
new System.Int32{m_value = 3}.CompareTo(2)
但是考虑到内存中的表示int
是4个字节,而内存中的表示System.Int32
是相同的4个字节.如果我们没有强大的类型系统禁止将一种类型视为另一种类型,我们可以随时将其中一种视为另一种类型.
现在,C#不允许我们这样做.我们做不到:
public struct MyInt32 { private int _value; } /* … */ MyInt32 = 3;
我们需要添加一个可以调用的强制转换方法,否则C#就会拒绝像这样工作.
CIL虽然没有这样的规则.它可以随时将一种类型视为另一种布局兼容类型.所以IL for (3).CompareTo(2)
:
ldc.i4.3 // Push the 32-bit integer 3 on the stack. ldc.i4.2 // Push the 32-bit integer 2 on the stack. call instance int32 [mscorlib]System.Int32::CompareTo(int32)
最后的调用只是假设3
是a System.Int32
并调用它.
这打破了C#type-safety的规则,但这些规则不是CIL的规则.C#编译器也不必遵循它强制执行的所有规则.
所以没有必要放任何东西m_value
,我们只是说"那里的那四个字节,它们就是一个m_value
字段System.Int32
",所以它神奇地完成了.(如果您知道C或C++会考虑如果您有两个具有等效成员的结构并将指针转换为其中一个类型void*
然后再返回另一个类型的指针会发生什么.这是一种不好的做法而且IIRC未定义而不是保证,但是允许较低级别的代码执行这些操作.
而这是如何走样的作品; .Net语言的编译器特殊情况我们需要调用基元上的方法来执行C#代码本身不允许的这种类型强制.
同样,在特殊情况下,值类型不能保持其自己类型的字段,并且允许System.Int32
具有int
字段,尽管通常struct S { public S value; }
不允许.