CLR via C#深解筆記六 - 泛型

来源:http://www.cnblogs.com/Dlonghow/archive/2016/02/03/5126133.html
-Advertisement-
Play Games

面向對象編程一個好處就是“代碼重用”,極大提高了開發效率。如是,可以派生出一個類,讓它繼承基類的所有能力,派生類只需要重寫虛方法,或添加一些新的方法,就可以定製派生類的行為,使之滿足開發人員的需求。 泛型(generic)是CLR和編程語言提供的一種特殊機制,它支持另一種形式的代碼重用,即“演算法重用


面向對象編程一個好處就是“代碼重用”,極大提高了開發效率。如是,可以派生出一個類,讓它繼承基類的所有能力,派生類只需要重寫虛方法,或添加一些新的方法,就可以定製派生類的行為,使之滿足開發人員的需求。 泛型(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指令來操縱這些值。   委托和介面的逆變和協變泛型類型實參    
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 註:最近看到不少介紹微軟ASP.NET Identity技術的文章,但感覺都不夠完整深入,本人又恰好曾在Adam Freeman所著的《Pro ASP.NET MVC Platform》一書中看到過有關ASP.NET Identity的完整介紹,為此特將有關章節翻譯出來,希望需要瞭解此項技術的園友能
  • 使用Log組件時,我們通常自定義ILogger介面,使用Log4Net等組件進行適配來定義不同的實現類。使用Log4Net日誌組件時,為了即方便單元測試又能使用配置文件,我們通過Log4Net的ILogger介面使用Log4Net,對Log4Net進行單元測試時我們可以通過使用MemoryAppen
  • 在MVC中,我們不僅可以使用它原來的方法,我們還可以自定義,這不不僅加大了我們開發的效率,同時使界面更簡潔。 具體什麼是擴展方法,你可以這樣理解,必須是靜態且在形參中第一個參數是以this開頭,大概先這樣理解下哈。接下來,我們就可以實現了。 首先,我們定義一個名為HtmlExtensions的類,在
  • 不使用特殊方法來處理請求生命周期事件 HttpApplication 類是全局應用類的基類,定義了可以直接使用的一般 C# 事件。那麼使用標準 C# 事件還是特殊方法那就是個人偏好的問題了,如果喜歡,也可以將這兩種方式混合起來使用。 1 using System; 2 using System.Co
  • Mobile An Introduction to Cordova: Basics Web Angular 2 versus React: There Will Be Blood How to Become a Better Node.js Developer in 2016 Debugging N...
  • linq的出現,帶給我們的是簡結,快速,可讀性,它由linq to sql,linq to object,linq to XML組成,我的博客之前有對linq to sql的講解,而今天,我將講一個linq to xml架構,將對於操作XML文件進行讀寫操作,它會讓你像使用linq to sql一樣
  • 過於笨重的網站將嚴重影響網站的最終體驗,主要表現在以下四個方面: 更大的下載量,導致更慢的用戶體驗。並不是每個人都擁有20M的網路連接,尤其是對於那些不發達地區。不管你的網站多麼優秀,用戶永遠不希望等待。 移動Web訪問正迅速發展,移動網民幾乎占到所有網民的1/4。在典型的3G網路連接下,一個1.7
  • 如果有個操作,我們需要過一會兒再做,或者每隔一段時間就要做一次。可以有很多種做法。 獨立線程 是的,對.NET Framework本身一知半解的程式員才會使用這種方案。不過,現實中這個方案其實並不少見。 public static void Repeat(this Action action, Ti
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...