熟悉C#開發的朋友們都應該知道,使用C#語言編寫的程序在編譯之后生成的文件被稱做為程序集,這其中又分為dll(類庫)和exe(可執行程序)兩種類型,而程序集當中的內容其實就CIL(Common Intermediate Language,公共中間語言)。CIL最初是隨着.NET由微軟一起發布的,因此有的地方也叫做MSIL(Microsoft Intermediate Language),后來進行了標准化就被稱作CIL,在一些書或文字中,CIL也會簡寫,其本質都是相同的東西。
1.CIL是繞不開的彎
在.NET平台下不僅僅支持C#這一門高級編程語言,這其中還包括但不限於:VB.NET、F#、C++,而這些要在.NET平台下使用的高級語言,最終編譯后都會生成為CIL代碼,所以說“CIL是繞不開的彎”。
為了證明這一特點,我們選用VB.NET來和C#做一個對比試驗,首先我們用VB.NET創建一個控制台程序並生成一個程序集。
1 Module Module1 2 3 Sub Main() 4 Dim text As String = "hello,world" 5 Console.WriteLine(text) 6 End Sub 7 8 End Module
代碼寫好后,現在需要通過微軟提供的IL DASM(反匯編程序)來查看這個程序集的內容。打開IL DASM后選擇VB.NET項目生成的exe文件,然后在界面的節點上選擇到Main方法節點,雙擊打開后解析出下圖的內容。
接下來我們使用和VB.NET相同的代碼編寫一個程序,再編譯后打開C#項目所生成的exe文件,在進行和上面同樣的操作,然后選擇到Main方法節點,雙擊打開后解析出下圖的內容。

如果你和我一樣實踐了上面的簡單試驗,那么我們可以初步推斷出:不管是VB.NET還是C#,只要是要運行在.NET平台下的高級編程語言,在編譯之后都會生成相同格式的程序集文件(dll或exe)並且內容都是CIL代碼。如果不同語言所實現的代碼都相同時,程序集所包含的CIL代碼也是類似的。

2.概念解析
我們通常去記住一個名稱概念的時候,如果死記硬背、生搬硬套,實際上是很難牢記於心的。為了記住這些概念我們還是要刨析其中的原理,去深刻理解這些術語背后的含義,中國文化不是就有這一道理嘛——格物致知。所以接下來我們深入的分析下,“公共中間語言”這個術語到底包含了哪些含義。
2.1.公共
在本文的對比試驗中,其實就體現出這個“公共”的內涵:不管是什么編程語言,甚至是你重新開發一套以自己名稱命名的語言也好,只要他想要在.Net平台上運行程序,那么它在編譯之后,所生成的程序集中的內容都會是CIL代碼。那么這也說明了,CIL不僅僅是為某個語言去單獨服務的,它是面向多種語言的。
2.2.中間
中間一詞是CIL最突出的一面,為什么要叫中間?怎么不叫上下或者前后?因為它不是最新CPU可以直接執行的本地機器語言,它只是一個過渡,中間語言還需要進行一個被稱為“Just-in-time(即時)”的二次編譯過程,才能轉變成計算機可以識別的指令,從而運行我們的程序邏輯。

打個通俗的比分,比如在吃東西的時候,嘴巴咀嚼吞咽食物后,食物在肚中的時候其實就是一個“中間”性質。因為吃進肚子的食物這並不代表食物的能量被我們直接吸收,它還需要我們的胃腸道進行消化(“二次編譯”)的過程,把食物消化成身體能接收的營養物質,我們人的身體才能從食物獲取能量。
2.3.語言
語言其實就是CIL的一種內容形式的描述,它本質上還是一種程序語言。只不過相對於C#來說,它並不是面向開發者特別易於使用的“低級”語言。
如果仔細觀察IL DASM解析后的CIL代碼,就可以看出CIL是一種基於堆棧的語言,並且它還提供了面向對象的語言特性。如果你願意,甚至可以直接編寫CIL代碼進行開發,並且使用CIL的編譯工具IL ASM(匯編程序)來對它進行編譯,只不過這種方式會讓我們的開發效率變的很低。
3.淺談托管和非托管
C#編寫的程序在編譯后會生成程序集,程序集中的內容是CIL代碼,而.NET運行時(CLR)會去執行程序集中的CIL代碼,那么只要是必須依托.NET運行時(CLR)才能執行的代碼就叫做“托管代碼”。相對的,不需要.NET運行時(CLR)就可以運行的代碼就叫做“非托管代碼”。
4.獨立性
C#源程序在編譯后會生成包含CIL代碼的程序集文件,這其實也代表它成為了一個獨立的個體,不在依賴於C#。因此程序集就可以由其他種類的語言所引用。那么這個時候,如果有VB.NET或者F#開發的項目其實就可以引用C#的程序集。程序集也就作為一個獨立的個體服務於.Net平台下不同語言開發的項目。
另外,基於CIL的中間性質說明了它並不是本地機器可以直接執行的指令,所以它沒有與某個固定的機器所綁定在一起,它可以被裝有.NET框架的任何機器上運行。
