.NET是微軟的新一代技術平台。對技術人員來說,想真正了解什麼是.NET,須先了解.NET技術出現的原因和它想解決的問題。時間追溯到20世紀90年代末,當時在微軟Windows平台上程式設計的程式員分為Win32 API、MFC和COM三大派。Win32 API是微軟向程式員開放的應用程式函數程式設計接口,函數多,零散繁瑣,開發工作量大;MFC是對API進行分類封裝的基礎架構,開發者隻需知道如何調用即可;COM是一種二進制、網絡标準,允許兩個聯通的元件互相通信而無需考慮該元件是由什麼語言實作,隻要該機器支援COM标準。這些技術都有着各自的優缺點,但是這些技術都有着一個共同的缺點,它們主要針對的是桌面程式,而不是Internet開發。下面以COM技術為例對比其和.NET的特點:
- COM中,所有的對象必須實作IUnknown接口,而在.NET中所有對象是實作Object類。接口程式設計在.NET中雖然是一個重要組成部分,但是已不是中心主題。
- COM中類型資訊作為.tlb檔案儲存在類型庫中,它和可執行代碼是分開的。而.NET中是将程式類型資訊和可執行代碼儲存在一個程式檔案中。
- COM中程式員必須記錄一個對象在程式中的引用數目,進而確定在所有的引用結束後将該對象删除。而在.NET中,垃圾回收器 (GC) 會自動記錄對象的引用情況,實作自動管理,并在合适的時機删除無主對象。
- COM使用HRESULT資料類型傳回運作時錯誤代碼。而.NET不再使用該類型,其中的運作時錯誤都當做異常處理,這樣使得代碼的運作更加安全。
- COM的應用必須在系統系統資料庫中注冊。系統資料庫中儲存了與作業系統的配置和應用程式有關的資訊。.NET應用不再需要注冊COM對象,這使得程式的安裝解除安裝操作變得更加簡單 (但.NET中存在全局程式集緩存GAC這一概念)。
新一代的.NET平台希望形成一個內建的、面向對象的開發架構,使得代碼的開發環境具有面向對象、一緻的程式設計體驗、行業标準通信(XML, HTTP, SOAP, JSON, WSDL)、程式部署簡單、語言獨立、互操作六大特點,代碼的執行環境能夠達到多平台(從伺服器、PC機到PDA)、既安全又高效。較之前的Windows程式設計環境,.NET架構為程式員帶來了相當大的改進,主要表現在以下4個方面:
- 面向對象的開發環境。系統為本地程式和分布式系統都提供了一緻的、面向對象的程式設計模型。此外,還為桌面應用程式、移動應用程式、Web開發提供了軟體開發接口,設計的目标範圍很廣,從桌面伺服器到手機。
- 垃圾自動回收。程式員可以從記錄程式對象的引用個數這樣的繁雜工作中解脫出來,不再需要執行釋放記憶體和檢查記憶體洩露這樣的工作。.NET架構可以實作自動管理記憶體,自動從記憶體中删除程式不再通路的對象。
- 互操作性。.NET語言的互操作性表現在不同的.NET語言、不同的作業系統平台,.NET語言和Win32 DLL、.NET語言和COM之間。
- NET語言的互操作。允許用不同的.NET語言編寫的軟體子產品無縫互動,一種.NET語言寫的程式可以使用另一種語言寫的類,真正做到語言無關。
- 平台調用(Platform invoke)。在.NET的代碼和非.NET語言寫的代碼之間互動,實作調用。例如可以在C#的代碼中直接調用标準的Win32 DLL到處的純C函數代碼。
- 與COM對象互操作。.NET元件可以實作COM元件的互相調用。
- 程式的部署。.NET架構編寫的程式與使用其他技術實作的程式部署要容易得多。一方面,.NET程式不需要在系統資料庫中登記資訊,這使得程式可以直接拷貝到目标機器上便可以運作;另一方面,.NET提供并行執行的功能,允許DLL的多個版本在同一台機器上同時存在,這使得每個可執行的程式都可以通路程式生成時的那個版本的DLL,而不會因為一個程式的更新,使得其他程式無法使用的情況發生。
目前越來越多的程式員開始将目光投向了.NET,這也使得微軟在最近幾年出現了不少新的動作。今年4月微軟宣布開源一批.NET庫和相關技術,11月微軟表示将不再把.NET和Visual Studio等關鍵軟體技術局限在Windows平台,今後還将相容Linux、Mac OS X、iOS和Android。
在了解.NET技術出現的原因和它想解決的問題後。下面将對.NET架構的各個組成部分進行一一介紹,以讓大家熟悉.NET架構的基本概念,也為将來在.NET平台上做應用開發奠定基礎。
如果把開發工具也包括進來的話,.NET架構由以下四個部分組成。
- Visual Studio內建開發環境IDE(Integration Development Environment),.NET的代碼開發環境,負責編譯時程式源代碼的編寫、編譯、調試和軟體部署。
- 基礎類庫BCL(Basic Class Language ),在編寫程式時可以直接調用這些預定義的類。
- 公共語言運作庫CLR(Common Language Runtime),.NET的代碼執行環境,負責運作時管理程式的執行
- 公共語言基礎結構CLI(Common Language Infrastructure),包括公共類型系統CTS(Common Type System)和公共語言規範CLS(Common Language Specification),為讓不同語言編寫的程式及庫能夠在.NET架構中進行良好地協作所約定的一套标準規範。
很多進階語言都需要通過編譯器編譯成機器語言的目标程式才能在目标機器上執行,.NET語言也不例外,但是.NET語言的編譯器在接受源代碼後并不是直接編譯成機器代碼,而是生成中間語言CIL(Common Intermediate Language)的程式集檔案,這個程式集可以是可執行的或者DLL。程式集中包括程式編譯的CIL,程式中使用的類型中繼資料和對其他程式集引用的中繼資料(如圖1)。
.NET中的編譯器有兩類。一類叫做.NET相容編譯器,它主要是實作将.NET相容語言編譯成中間語言CIL的程式集,另一種稱為實時編譯器JIT(Just in Time),這種編譯器在程式被調用時将CIL編譯成本機代碼。前者是在編譯階段執行,後者是在運作時執行。
在第二次編譯時,程式集中的可執行代碼隻在需要的時候由JIT編譯器編譯,編譯後将會在記憶體中緩存起來以備後來的程式執行。這也就意味着不被調用的代碼不會被編譯成本機代碼,而且被調用到的代碼隻被編譯一次。
圖1 編譯時和運作時過程概覽
如果把.NET架構比作為一個社會的話,各種.NET相容語言就是這個社會中使用的交流語言。因為每種程式設計語言都有一組内置的類型,用來表示整數、浮點數和字元等基本類型,這些類型的特征因程式設計語言和平台的不同而不同。為了讓不同的語言編寫的程式及庫能在一起良好地協作,需要有一組這樣的标準來約定。
公共語言基礎結構CLI(Common Language Infrastructure)就是這樣一組标準,它把所有.NET架構的元件連接配接成一個内聚的、一緻的系統。它展示了系統的概念和架構,并詳細說明了所有軟體必須堅持的規則和約定。CLI包括公共類型系統CTS(Common Type System)和公共語言規範CLS(Common Language Specification)。CTS主要是對托管代碼進行了約定,包括豐富的内置類型以及每種類型固有的、特有的性質,規定所有的類型都繼承自公共的基類Object類。有了CLS,可以使用任何.NET相容語言進行互操作,而不會出現系統類型和使用者自定義類型之間的沖突。
這四個組成部分中,核心元件是公共語言運作庫CLR,這也是.NET能實作其開發環境和執行環境特點的核心技術所在,它在作業系統的頂層,負責管理程式的執行。CLR是在程式的運作時執行包括檢查程式集的安全特性、記憶體配置設定、在程式被調用時将程式集中的被調用部分可執行代碼發送給實時編譯器JIT。一旦程式CIL編譯成本機代碼,CLR就在它運作時管理它,執行像釋放無主記憶體、檢查數組邊界、檢查參數類型和管理異常等任務。是以,也産生了兩個重要的術語:托管代碼和非托管代碼。
托管代碼(Managed Code) —— 指的是.NET架構編寫的代碼,需要CLR進行管理。
非托管代碼(Unmanaged Code) —— 不再CLR控制之下運作的代碼,比如Win32 C / C++ DLL。
圖2 CLR概覽
縮寫 | 全稱 | 中文 |
API | Application Program Interface | 應用程式接口 |
MFC | Microsoft Framework Class | 微軟架構類 |
COM | Component | 元件 |
GAC | Global Assemble Cache | 全局程式集緩存 |
GC | Garbage Collector | 垃圾回收器 |
IDE | Integrated Development Environment | 內建開發環境 |
BCL | Base Class Library | 基礎類庫 |
CLR | Common Language Runtime | 公用語言運作庫 |
CLI | Common Language Infrastructure | 公共語言基礎結構 |
JIT | Just in Time | 試試編譯器 |
DLL | Dynamic Linkable Library | 動态連結庫 |
CTS | Common Type System | 公共類型系統 |
CLS | Common Language Specification |