詳解C#泛型(三)

来源:https://www.cnblogs.com/minotauros/archive/2018/11/23/10006796.html
-Advertisement-
Play Games

一、前面兩篇文章分別介紹了定義泛型類型、泛型委托、泛型介面以及聲明泛型方法: 詳解C#泛型(一) 詳解C#泛型(二) 首先回顧下如何構建泛型類: 其中,尖括弧<>中的T代表的是該泛型類的類型參數,在使用時可以指定其類型,例如,指定類型參數為整數類型,創建封閉式構造類MyClass<int>: 二、這 ...


  一、前面兩篇文章分別介紹了定義泛型類型、泛型委托、泛型介面以及聲明泛型方法:

  詳解C#泛型(一)

  詳解C#泛型(二)

  首先回顧下如何構建泛型類:

public class MyClass<T>
{
    public void MyFunc()
    {
        //
    }
}

  其中,尖括弧<>中的T代表的是該泛型類的類型參數,在使用時可以指定其類型,例如,指定類型參數為整數類型,創建封閉式構造類MyClass<int>:

MyClass<int> myObj = new MyClass<int>();

  二、這一篇我們瞭解一下泛型的作用機制,泛型是運行時起作用的一套機制,根據運行時類型參數被指定為值類型還是引用類型其使用方式有所不同:

  1.當類型參數被指定為值類型時,會在第一次指定該特定值類型的類型時創建該類型唯一的專用化泛型類型,泛型類型中的類型參數會被替換為相應的值類型;

  ※此時,運行時會創建不同封閉式構造類型的類型信息對象,它們的類型句柄指向不同的類型信息對象,不同封閉式構造類型的方法句柄也指向不同的方法信息對象;

  2.當類型參數被指定為引用類型時,會在第一次指定任意引用類型時創建一個通用化泛型類型,泛型類型中的類型參數會被替換為該引用類型,併在之後每次指定為引用類型時重用該泛型類型並修改其中類型參數的類型;造成這種差異的原因可能在於所有的引用大小相同;

  ※此時,運行時依然會創建不同封閉式構造類型的類型信息對象,它們的類型句柄也指向不同的類型信息對象,但是它們共用一套方法句柄,即不同封閉式構造類型的方法句柄指向同一個方法信息對象;
  3.對於給定的泛型類:

public class MyClass<T>
{
    public void MyFunc()
    {
        //…
    }
}
獲取不同封閉式構造類型的類型句柄和方法句柄:
Type type1 = typeof(MyClass<int>);
Type type2 = typeof(MyClass<long>);
Type type3 = typeof(MyClass<string>);
Type type4 = typeof(MyClass<Array>);
//以下類型句柄各不相同
Console.WriteLine(type1.TypeHandle.Value);
Console.WriteLine(type2.TypeHandle.Value);
Console.WriteLine(type3.TypeHandle.Value);
Console.WriteLine(type4.TypeHandle.Value);
//最後兩個方法句柄相同,其它方法句柄各不相同
Console.WriteLine(type1.GetMethod("MyFunc").MethodHandle.Value);
Console.WriteLine(type2.GetMethod("MyFunc").MethodHandle.Value);
Console.WriteLine(type3.GetMethod("MyFunc").MethodHandle.Value);
Console.WriteLine(type4.GetMethod("MyFunc").MethodHandle.Value);

  ※在訪問任何泛型類型之前,CLR會先創建MyClass<>的類型信息對象;

  列印結果:

  

  可以發現,最後兩個泛型類型的MyFunc方法的方法句柄指向相同;但是不同類型參數的情況下,還是會創建對應的泛型類型對象,這使得泛型單例成為可能:

  三、對於封閉式構造類型,只要其類型參數不完全相同,CLR就會在初次訪問該類型之前創建該類型的類型信息對象並調用其對應唯一的靜態構造函數,例如對於有靜態構造函數的泛型類MyClass<T>,在初次訪問MyClass<int>、MyClass<string>等封閉式構造類之前都會調用一次其對應唯一的靜態構造函數,這也是創建泛型單例的基礎:

public class MyClass<T>
{
    static MyClass()
    {
        Console.WriteLine(typeof(T).FullName);
    }
}
MyClass<int> obj1 = new MyClass<int>();
MyClass<long> obj2 = new MyClass<long>();
MyClass<Array> obj4 = new MyClass<Array>();  

  列印結果:

  

  四、運行時動態構建泛型:

Type myType = typeof(MyClass<>);  //獲取未指定任何類型參數的開放式構造類的類型信息,多個類型參數時添加,:typeof(MyClass<,>)
myType = myType.MakeGenericType(typeof(int));  //通過類型信息的實例方法MakeGenericType()構建指定所有類型參數的封閉式構造類的類型信息,如未指定所有類型參數會拋出異常ArgumentException
//也可以直接獲取封閉式構造類的類型信息,當類型參數在一開始就確定時推薦使用此種方式
//myType = typeof(MyClass<int>);  //多個類型參數時需要同時指定:typeof(MyClass<int, string>)

  註意:通過反射只可以獲取未指定任何類型參數的開放式構造類MyClass<,>的類型信息和指定所有類型參數的封閉式構造類MyClass<int, string>的類型信息,即無法獲取MyClass<int, >的類型信息;

 


如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的認可是我寫作的最大動力!

作者:Minotauros
出處:https://www.cnblogs.com/minotauros/

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...