程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> CLR via C#深解筆記六,

CLR via C#深解筆記六,

編輯:C#入門知識

CLR via C#深解筆記六,


面向對象編程一個好處就是“代碼重用”,極大提高了開發效率。如是,可以派生出一個類,讓它繼承基類的所有能力,派生類只需要重寫虛方法,或添加一些新的方法,就可以定制派生類的行為,使之滿足開發人員的需求。 泛型(generic)是CLR和編程語言提供的一種特殊機制,它支持另一種形式的代碼重用,即“算法重用”。   簡單地說,開發人員先定義好一個算法,比如排序、搜索、交換、比較或轉換等。但是,定義算法的開發人員並不設定該算法要操作什麼數據類型;該算法可以廣泛地應用於不同類型的對象。然後,另一個開發人員只要指定了算法要操作的具體數據類型,就可以使用這個現成的算法了。例如,可用一個排序算法來操作Int32和String等類型的對象,或用一個比較算法來操作DateTime和Version等類型的對象。大多數算法都封裝在一個類型中,CLR允許創建泛型引用類型和泛型值類型,但不允許創建泛型枚舉類型。還允許創建泛型接口和泛型委托。   泛型為開發人員提供了一下優勢: #1,源代碼保護。 #2,類型安全。編譯器和CLR能理解開發人員的意圖,並保證只有與指定數據類型兼容的對象才能隨同算法使用。 #3,更加清晰的代碼。減少了源代碼中必須進行的轉型次數,代碼更容易編寫和維護。 #4,更佳的性能。創建泛型算法來操作一種具體的值類型,所以值類型的實例能夠以傳值方式傳遞,CLR不再需要執行任何裝箱操作。ArrayList來操作值類型(如Int32),會造成大量裝箱操作,大量的垃圾回收。 泛型最明顯的應用就是集合類。FCL已經定義了幾個泛型集合類,其中,大多數類都在System.Collections.Generic 和System.Collections.ObjectModel命名空間中。   泛型基礎結構 開發類型和封閉類型 我們關注CLR如何為應用程序使用的每個類型創建一個怎樣的內部數據結構,這種數據結構稱為類型對象(type object)。具有泛型類型參數的類型仍然是類型,CLR同樣會為它創建一個內部類型對象。無論引用類型(類)、值類型(結構)、接口類型,還是委托類型,這一點都成立。具有泛型類型參數的類型稱為開放類型(open type), CLR禁止構造開發類型的任何實例,類似CLR禁止構造接口類型的實例, 如List<>。   代碼引用一個泛型類型時,可指定一組泛型類型實參。假如為所有類型實參傳遞的都是實際數據類型,類型就稱為封閉類型(closed type),CLR允許構造封閉類型的實例,如List<String> 。需要注意的是,CLR會在類型對象內部分配類型的靜態字段,因此每個封閉類型都有自己的靜態字段。例如,List<T>定義了任何靜態字段,都不會在一個List<DateTime>和一個List<String>之間共享:每個封閉類型對象都有它自己的靜態字段。假如一個泛型類型定義了一個靜態構造器,那麼針對每個封閉類型,這個構造器都會執行一次。在泛型類型上定義一個靜態構造器的目的是保證傳遞的類型實參滿足特定的條件(約束)。如,希望一個泛型類型只用於處理枚舉類型,就可以如下定義: internal sealed class GenericTypeThatRequiresAnEnum<T> {      static GenericTypeThatRequiresAnEnum() {           if(!typeof(T).IsEnum) {                throw new ArgumentException("T must be an enmuerated type");           }      } }   CLR提供了一個名為約束的功能,可利用它更好地定義一個泛型類型來支出哪些類型實參是有效的。   代碼爆炸   使用泛型類型參數的一個方法在進行JIT編譯時,CLR獲取方法的IL,用指定的類型實參進行替換,然後創建恰當的本地代碼(這些代碼是為操作指定數據類型的方法“量身定制”的)。這樣做有一個缺點:CLR要為每一種不同的方法/類型組合生成本地代碼。這個現象稱為代碼爆炸(code explosion)。它可能造成應用程序的工作集顯著增大,從而損害性能。   CLR其實內建了一些優化措施,能夠緩解代碼爆炸。假如為一個特定的類型實參調用一個方法,以後再次使用相同的類型實參來調用這個方法。CLR只會為這個方法/類型組合編譯一次代碼。如果一個程序集使用List<DateTime>, 一個完全不同的程序集(加載到一個AppDomain中)也使用List<DateTime>, CLR只會為List<DateTime>編譯一次方法。這樣顯著緩解了代碼爆炸。 CLR還提供了另一個優化措施,它認為所有引用類型實參都是完全相同的,所以代碼可以共享。如,CLR為List<String>的方法編譯的代碼可直接用於List<Stream>的方法,因為String和Stream均為引用類型。事實上,對於任何引用類型,都會使用相同的代碼。CLR之所以能執行這個優化,是因為所有引用類型的實參或變量實際只是指向堆上的對象的指針,而對象指針全部是以相同的方式來操作的。 但是,某個類型實參是值類型,CLR就必須專門為這個值類型生成本地代碼,因為值類型的大小不定,還可能要用不同的本地CPU指令來操縱這些值。   委托和接口的逆變和協變泛型類型實參    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved