Int32
结构体的内容后,我意识到int
和Int32
是同义词。在Int32
结构体源代码中,有一个internal int m_value
字段。如果我的知识是正确的,我们赋给int变量的值存储在
m_value
中(我是对的吗?)。但是我的疑问是,在我们执行int i = 7;
时,值是如何存储在m_value
中的。我没有在
Int32
结构体的源代码中看到任何隐式操作符,因此值无法存储在m_value
中。有人可以帮我解决这个问题吗?
int
在 C# 中代表着与 CIL 中的 int32
相同的东西,它是一个 4 字节的原始数据类型,通常被视为有符号数(尽管 CIL 可以在没有强制转换的情况下对其进行无符号操作)。
它是我们可以用来创建更复杂的结构和类的最低级构建块之一。
但是作为这样一个构建块,它本身没有定义任何方法。
而 System.Int32
看起来很像一个包装了 int
/int32
的结构体,并提供了一些方法。
让我们把它看作是这样的;想象一下在没有将 int
别名化为 System.Int32
的世界中,它会是什么样子:
在这种假设的情况下,我们只能在将其视为特殊的“装箱 int”类型时使用 System.Int32
提供的方法,在需要时从 int
创建一个 System.Int32
,并在需要时再次提取 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;
(3).CompareTo(2)
的IL代码如下: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
是一个System.Int32
,并将其调用。这违反了C#类型安全的规则,但这些规则不是CIL的规则。 C#编译器也不必遵循其强制执行的所有规则。m_value
中,我们只需说“哦,那四个字节,它们是System.Int32
的m_value
字段”,于是就神奇地完成了。(如果您了解C或C ++,请考虑一下如果您有两个具有等效成员的结构体,并将指向其中一种类型的指针转换为void *
,然后再转换回另一种指针会发生什么。这是一种不好的做法,并且我IRC未定义而不是保证,但更低级别的代码允许进行这些操作)。System.Int32
具有int
字段,尽管通常不允许struct S { public S value; }
。这就是语言的工作方式,伙计!
在该语句中
int i = 7;
Int32
变量(即 int i
部分)。然而,你正在将它赋值为 7
。在 C#(以及许多其他语言)中,7
被称为字面量。这意味着 7
已经是 Int32
的实例了!就像这样:public class ClassA {
public int i;
}
还有一个 ClassA
的实例:
ClassA obj = new ClassA ();
obj.i = 1;
然后你这样做:
ClassA a = obj;
你说:“我没有看到 ClassA
中有任何隐式操作符,使得值可以存储在 i
中。”
但是 obj
已经是一个合法的对象!就像 7
一样。
new ClassA()
,所以它不是类似的。要类似,它必须是 ClassA obj = 1
并且 没有定义任何隐式运算符。这在 C# 中行不通,但 C# 在进行别名时并不需要遵守 C# 所强制执行的规则。 - Jon Hanna阅读核心框架源代码时,很难跟上正在发生的事情。
“当我们给出int i = 7;
时,值如何存储在m_value中?”
首先,当C#编译器看到int
时,它只是假装你说了System.Int32
(*)。同样,当它看到7
时,它会说:“啊哈!那是一个整数字面量。我将把它存储在System.Int32
中”。然后它创建变量i
(正确类型的变量),并用它创建的值初始化它。
(*)这意味着源http://referencesource.microsoft.com/#mscorlib/system/int32.cs,225942ed7b7a3252有:
public struct Int32 : *various bases*
{
internal Int32 m_value;
...这有点令人困惑(而且通常不合法)。
int
变量时,如何初始化System.Int32):http://stackoverflow.com/questions/25449498/instantiation-and-initialization-of-value-types-vs-reference-types _“int是一种内置类型。编译器知道如何为它生成IL。int的类型被“烘焙”到编译器为赋值生成的CIL中:.locals init ([0] int32 a) ldc.i4.s 5 stloc.0
"_ - Tim Schmelter