C#中int和System.Int32理解總結
最近園里的TeamOne寫了一篇《[C#] int與System.Int32有什么區別》,發現里面有不少精彩的評論,所以忍不住想這篇文章總結一下:
本文的主要參考資料:
1.《理解C#中的System.Int32和int:并非雞和雞蛋》@Author:Dixin
2.《[C#] int與System.Int32有什么區別》@Author:TeamOne
一.問題的來源
MSDN說,int只不過是System.Int32的別名而已,也就是說:
System.Int32 i=1;
應該是等價的,或者說毫無區別的。但在Dixin在用Reflector對.Net Framework的mscorlib.dll進行反匯編時,發現事情好像并不是這樣,看下圖:
上圖是Dixin通過Reflector對mscorlib.dll進行反匯編后看到的System.Int32的定義,在上圖中,我們看到Int32的定義中用到了int,如果按MSDN中說,int只是System.Int32的別名,那問題就來了:
(1).使用int和使用System.Int32是沒有區別的。
(2).在C#的Struct定義中,字段中存在類型為自己的變量,是不允許的,例子如下:
{
public Test value;
}
上面這個例子編譯會失敗。由于System.Int32等價于int ,所以System.Int32的編譯也應該會失敗的!但事實上是,Reflector反編譯出來的代碼的確顯示System.Int32定義中使用了int。這就不禁讓人懷疑,int和System.Int32的關系到底是不是如MSDN所說的這么簡單呢??究竟int是System.Int32的別名呢?還是System.Int32對int進行了封裝呢?
二.int和System.Int32的關系
下圖是我從微軟官方介紹里截取的,我們先簡單看一下.Net Framework的架構:
.Net Framework是一個基礎平臺,它要支持建立在此基礎上的各種語言,以及跨語言程序之間的通信。如圖:
由于上述原因,.Net Framework對外提供的資源必須是通用的,并且避免使用某種語言的特有稱呼,以免造成不必要的混淆。
于是,這就有了int和System.Int32,它們的關系如下圖:
System.Int32是.Net Framework對32位整數的標識,MSDN對這種類型標示的稱呼是User Type。而int則是c#語言里面的特有稱呼(這里它對應的.Net Framework里的System.Int32),MSDN對c#的int的稱呼是Keyword。int就是System.Int32的別名而已!
那為什么我們在用Reflector反編譯mscorlib.dll的時候,會得出第一幅圖那種結果呢?
是這樣的,在.Net Framework運行庫里,有一種最基礎的數據類型,叫“基元類型(primitive)”。這種數據類型是只提供給.Net Framework內部使用,外面是看不見的。其實在真正微軟的System.Int32的源碼中,用到的應該是int32。但是由于int32不是c#提供的類型,所以Reflector會自動把int32逆向為c#的int,這也就是為什么我們會在System.Int32定義中看到int的存在了。
這里我引用Dixin文章里的一段IL代碼證明int32的存在:>
C#代碼:
{
return value * 2;
}
對應得IL代碼:
{
.maxstack 2
.locals init (
[0] int32 CS$1$0000)
L_0000: nop
L_0001: ldarg.1
L_0002: ldc.i4.2
L_0003: mul
L_0004: stloc.0
L_0005: br.s L_0007
L_0007: ldloc.0
L_0008: ret
}
想了解更多的關于“基元類型”的資料,可以參考這篇文章《認識基元類型、FCL類型及與CLR的相容情況》。
三.System.Int32在64位機器上
System.Int32在64位機器上還是表示32位的整數,也就是說C#的int在64位機器上也還是表示32位的整數。至于為什么,看下圖:
如果System.Int32在64位機器為64bit,那么,這將會使在32位機器上的C#程序難以和64位上的C#程序溝通,試想一下,要把64bit的數據塞進32bit的空間中是一件多惡心的事情啊!所以,System.Int32在64位機器還是表示32位的長度,是很合理的。