如果Int32只是int的别名,那么Int32类如何使用int?

时间:2013-04-19 21:35:13

标签: c# compiler-construction internals

浏览.NET Framework Reference Source的.NET源代码,只是为了好玩。并找到了一些我不明白的东西。

有一个 Int32.cs 文件,其中包含Int32类型的C#代码。不知怎的,这对我来说似乎很奇怪。 C#编译器如何编译Int32类型的代码?

public struct Int32: IComparable, IFormattable, IConvertible {
    internal int m_value;

    // ... 
}

但在C#中这不是非法的吗?如果int只是 Int32别名,则无法使用Error CS0523进行编译:

  

类型为'struct1'的struct member'struct2 field'会在struct layout中产生一个循环。

编译器中是否有一些魔法,或者我完全偏离轨道?

2 个答案:

答案 0 :(得分:48)

  

在C#中不是非法的吗?如果“int”只是“Int32”的别名,则无法使用错误CS0523进行编译。编译器中有一些魔法吗?

是;错误是在编译器中故意抑制的。如果有问题的类型是内置类型,则完全跳过循环检查器。

通常这种事情是非法的:

struct S { S s; int i; }

在这种情况下,S的大小是未定义的,因为无论S的大小如何,它必须等于它自己加上int的大小。没有这样的尺寸。

struct S { S s; }

在这种情况下,我们没有信息可以推断出S的大小。

struct Int32 { Int32 i; }

但在这种情况下,编译器提前知道System.Int32是四个字节,因为它是一种非常特殊的类型。

顺便提一下,C#编译器(以及,就此而言,CLR)如何确定一组结构类型何时是循环的细节非常有趣。我会尝试在某个时候写一篇博客文章。

答案 1 :(得分:13)

intInt32的别名,但您正在查看的Int32结构只是元数据,它不是真正的对象。 int m_value声明可能只是为了给结构提供适当的大小,因为它实际上从未在其他任何地方被引用(这就是允许它存在的原因)。

因此,换句话说,编译器类可以将其保存为一个问题。讨论了in the MSDN Forums主题。

从讨论中,这里是所选答案的引用,有助于确定声明的可能性:

  

虽然该类型包含整数m_value字段 - 的确如此   字段永远不会被引用。在每种支持方法中(CompareTo,   ToString等),改为使用“this”。有可能是   仅存在m_value字段以强制结构具有   适当的大小。

     

我怀疑当编译器看到“int”时,它会将其转换为“a   引用mscorlib.dll中的System.Int32,稍后要解决“,和   因为它正在构建mscorlib.dll,所以它最终会产生一个周期性的   引用(但不能引起问题,因为m_value   从未使用过)。如果这个假设是正确的,那么这个技巧会   仅适用于特殊编译器类型。

进一步阅读,可以确定结构只是元数据,而不是真实对象,因此它不受相同的递归定义限制的束缚。