Framework類庫
.NET Framework 包含 Framework類庫(Framework Class Library, FCL)
FCL是一組DLL程序集的統稱,類型數量太多,因此相關的類型會被放到單獨的命名空間,如:
System(包含了每個應用程序都要用到的基本類型:Object/…)
System.Data
System.IO
System.Text
等等
通用類型系統
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
完全公開
「代碼的語言」與「代碼的行為」
無論使用哪一種語言,類型的行為都完全一致
語言會以開發者自身最熟悉的方式公開它的語法和類型規則,在編譯成程序集時,它會再將其特有的語法映射到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::get_Item
還有一些被編譯成了.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 )
例子各構造與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