C#筆記 – CLR的執行模型(三) 類庫及語言規範
Framework類庫
- .NET Framework 包含 Framework類庫(Framework Class Library, FCL)
- FCL是一組DLL程序集的統稱,類型數量太多,因此相關的類型會被放到單獨的命名空間,如:
- System(包含了每個應用程序都要用到的基本類型:Object/…)
- System.Data
- System.IO
- System.Text
- 等等
- FCL是一組DLL程序集的統稱,類型數量太多,因此相關的類型會被放到單獨的命名空間,如:
通用類型系統
- CLR一切都圍繞類型展開,類型是CLR的根本
- 類型向應用程序和其他類型公開了功能
- 類型使兩種編程語言寫的代碼之間可以溝通
- Microsoft對「類型」的定義和行為制定了規範——「通用類型系統」(Common Type System, CTS)
- Microsoft把CTS和.NET Framework的其他組件已交給ECMA完成標準化工作,最後形成的標準稱為「公共語言基礎結構」(Common Language Infrastructure, CLI)
CTS規範
- 一個類型可包含0個或多個成員
- 字段
- 作為對象狀態的數據變量
- 方法
- 針對對象執行操作的函數
- 方法有一個名稱、簽名、一個/多個修飾符
- 簽名指定參數數量及其類型、返回值及其類型
- 屬性
- 對於調用者像是字段
- 對於實現者像是方法
- 事件
- 實現對象之間的通知機制
- 字段
- 可見性規則及訪問規則
- private
- 同一個類內可訪問
- family
- 派生類可訪問,即使不在同一個程序集中
- 在C#中,等價於protected
- family and assembly
- 派生類可訪問,且需要在同一程序集中
- C#不存在該限制
- assembly
- 同一程序集中可訪問
- C#中,等價於internal
- family or assembly
- 派生類或同一程序集中可訪問
- C#中,等價於 protected internal
- public
- 完全公開
- private
- 「代碼的語言」與「代碼的行為」
- 無論使用哪一種語言,類型的行為都完全一致
- 語言會以開發者自身最熟悉的方式公開它的語法和類型規則,在編譯成程序集時,它會再將其特有的語法映射到IL(CLR的「語言」)
- 最終都是由CLR的CTS來定義類型的行為
公共語言規範
- CLR集成了所有語言,用一種語言創建的對象在另一種語言中,和用後者創建的對象具有相同地位,使得不同語言創建的對象之間可以進行相互通信
- 各種編程語言之間存在極大區別,要創建很容易從其他編程語言中訪問的類型,只能從自己的語言中挑選其他所有語言都支持的功能 => 公共語言規範(Common Language Specification,CLS),它定義了一個最小功能集。
- 任何編譯器只要支持這個功能集,生成的類型就能兼容其他符合CLS、面向CLR的語言生成的組件
- 不同於CLR/CTS,CLS定義的只是一個子集
- 如果開發類型和方法時,希望它對外「可見」,能從符合CLS的任何編程語言中訪問,就需要遵守CLS定義的規則
- CLR/CTS提供的是一個功能集,如果開發者用IL匯編寫程序,就可以使用CLR/CTS全部功能,一般語言(如C#)只公開了部分的功能
- CLS定義了不同的語言(如C#、Fortan、Visual Basic)之間都必須支持的最小功能集

-
在CLR中,類型的每個成員要麼是字段(數據),要麼是方法(行為)
-
- 每一種編程語言都必須能訪問字段和調用方法
- 在編程語言中,往往會對字段和方法進行了額外的抽象,從而使編程變得更簡單。比如以下概念的公開:
- 枚舉
- 數組
- 屬性
- 委托
- 構造器
- 操作符重載
- 等等
- 編譯器在源代碼中遇到其中任何一樣,都必須將其轉換成字段和方法,使CLR和其他任何編程語言可以訪問這些構造
- 如下例的源碼與IL代碼:
-
using System; internal sealed class Test { //Constructor public Test() { } //終結器 ~Test() { } //操作符重載 public static bool operator == (Test t1, Test t2) { return true; } public static bool operator != (Test t1, Test t2) { return false; } public static Test operator + (Test t1, Test t2) { return null; } //屬性 public string AProperty { get { return null; } set { } } //索引器 public string this[int x] { get { return null; } set { } } //事件 event EventHandler AnEvent; }
- 在編程語言中,往往會對字段和方法進行了額外的抽象,從而使編程變得更簡單。比如以下概念的公開:
- 每一種編程語言都必須能訪問字段和調用方法

-
當中大部分的構造都被編譯成了.method(方法)
-
op_Addition
.method public hidebysig specialname static class CLR_Via_CSharp_4._0.Test op_Addition(class CLR_Via_CSharp_4._0.Test t1, class CLR_Via_CSharp_4._0.Test t2) cil managed { // 程式碼大小 7 (0x7) .maxstack 1 .locals init (class CLR_Via_CSharp_4._0.Test V_0) IL_0000: nop IL_0001: ldnull IL_0002: stloc.0 IL_0003: br.s IL_0005 IL_0005: ldloc.0 IL_0006: ret } // end of method Test::op_Addition -
get_Item
.method public hidebysig specialname instance string get_Item(int32 x) cil managed { // 程式碼大小 7 (0x7) .maxstack 1 .locals init (string V_0) IL_0000: nop IL_0001: ldnull IL_0002: stloc.0 IL_0003: br.s IL_0005 IL_0005: ldloc.0 IL_0006: ret } // end of method Test -
還有一些被編譯成了.field(字段)
- AnEvent : private class [System.Runtime]System.EventHandler
-
.field private class [System.Runtime]System.EventHandler AnEvent .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [System.Diagnostics.Debug]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [System.Diagnostics.Debug]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
-
- AnEvent : private class [System.Runtime]System.EventHandler
-
例子各構造與CLR字段/方法對應關係表
-
成員 成員類型 對應的編程語言構造 AnEvent 字段 事件 .ctor 方法 構造器 Finalize 方法 終結器 add_AnEvent 方法 事件的add方法 get_AProperty 方法 屬性的get方法 get_Item 方法 索引器的get方法 op_Addition 方法 +操作符的重載方法 op_Equality 方法 ==操作符的重載方法 op_Inequality 方法 !=操作符的重載方法 remove_AnEvent 方法 事件的remove方法 set_AProperty 方法 屬性的set方法 set_Item 方法 索引器的set方法
-
-
另外還有.class、.custom、AnEvent、AProperty、Item的節點不屬於字段/方法
- 這些節點標識了類型的其他元數據,它們只提供了一些額外信息,供CLR、編程語言或工具訪問
- 在這些節點裡面,往往包含了指向其他方法節點的信息
-
AProperty
-
.property instance string AProperty() { //指向了get_AProperty方法 .get instance string CLR_Via_CSharp_4._0.Test::get_AProperty() //指向了set_AProperty方法 .set instance void CLR_Via_CSharp_4._0.Test::set_AProperty(string) } // end of property Test::AProperty
-
-
AnEvent
-
.event [System.Runtime]System.EventHandler AnEvent { //指向了add_AnEvent方法 .addon instance void CLR_Via_CSharp_4._0.Test::add_AnEvent(class [System.Runtime]System.EventHandler) //指向了remove_AnEvent方法 .removeon instance void CLR_Via_CSharp_4._0.Test::remove_AnEvent(class [System.Runtime]System.EventHandler) } // end of event Test::AnEvent
-
-
-
參考書目
- 《CLR via C#》(第4版) Jeffrey Richter