網站首頁 編程語言 正文
".NET泛型"系列:
ASP.NET泛型一之泛型簡介與基本語法
ASP.NET泛型二之泛型的使用方法
ASP.NET泛型三之使用協變和逆變實現類型轉換
ASP.NET泛型四之使用Lazy<T>實現延遲加載
.NET泛型或許是借鑒于C++泛型模版,借助它可以實現對類型的抽象化、泛型處理,實現了類型和方法之間的解耦。一個最經典的運用是在三層架構中,針對不同的領域模型,在基接口、基類中實現針對各個領域模型的泛型處理。
為什么需要泛型
不用泛型
來看一個比較類型的方法。
public class Calculator { public static bool AreEqual(int value1, int value2) { return value1 == value2; } }
在客戶端調用。
class Program { static void Main(string[] args) { bool result = Calculator.AreEqual(1, 2); if (result) { Console.WriteLine("相等"); } else { Console.WriteLine("不等"); } Console.ReadKey(); } }
運行結果:不等
不用泛型的缺點一:不是類型安全
如果我們想使用現在的方法來比較字符串類型。
bool result = Calculator.AreEqual("A", "B");
這時,看到編譯器報錯。從這點來看,AreEqual()方法不是類型安全的方法,當輸入string類型,編譯器就會報錯。
如果把AreEqual()方法的參數類型改成object,編譯器就不再報錯。
public class Calculator { public static bool AreEqual(object value1, object value2) { return value1 == value2; } }
以上,運行也正常。
不用泛型的缺點二:裝箱與拆箱導致性能降低
現在,對于AreEqual(object value1, object value2),從方法本身來講是沒有問題的,但在客戶端調用的時候,比如我們還是想比較值類型。
bool result = Calculator.AreEqual(1, 2);
在運行時,當整型值類型參數1和2傳遞、賦值給AreEqual(object value1, object value2)中的引用類型參數value1和value2的時候,發生了一次"裝箱"操作。而當把引用類型轉換成值類型的時候,又會發生一次"拆箱"操作,這導致性能的降低。
使用泛型
把AreEqual()改成泛型方法。
public class Calculator { public static bool AreEqual<T>(T value1, T value2) { return value1.Equals(value2); } }
于是,在客戶端可以這樣:
bool result = Calculator.AreEqual<string>("A", "A"); bool result = Calculator.AreEqual<int>(5, 3);
由此,使用泛型的好處有:
1、實現了方法和類型的解耦。
2、不會造成類型轉換,規避了因裝箱于拆箱引起的性能問題。
3、泛型保證了類型的絕對安全。
當然,還可以把T的位置放在類上:
public class Calculator<T> { public static bool AreEqual(T value1, T value2) { return value1.Equals(value2); } }
然后這樣使用:
bool result = Calculator<string>.AreEqual("A", "A"); bool result = Calculator<int.AreEqual(1, 2);
泛型的運行時本質
CLR中有專門的IL指令支持泛型操作。
→初次編譯時,生成IL代碼和元數據,T只是類型占位符,在編譯時不進行實例化
→JIT編譯時,以實際類型替換元數據中的T占位符
→將元數據轉換為本地代碼
泛型語法
class MyArray<T> where T : Student, new() { private T[] _items; public T myData; public MyArray() { myData = default(T); } public void Add(T item) {} }
創建泛型實例要指定實際的數據類型:
MyArray<Int32> myArr = new MyArray<Int32>();
值類型的默認值為0,引用類型的默認值為null,使用泛型默認值:
myData = default(T);
泛型約束:
- T : 基類名,表示必須是基類名的派生類
- T :new(), 表示必須具有無參構造函數,new()約束必須放在最后面
- T :struct, 表示必須是值類型
- T :class, 表示必須是引用類型
- T :接口名,表示必須實現該接口,或實現該接口的接口
泛型類本質上仍然是一個類,依然可以繼承:
internal class GenericeComparer<T> : Comparer<T> where T : IComparable<T> class MyArray<T> : ArrayList
典型的泛型類
在System.Collections.Generic命名空間和System.Collections.ObjectModel中,定義了不同的泛型類和泛型接口,這些泛型多為集合類。
- List<T> 對應ArrayList集合類
- SortedList<TKey, TValue> 對應SortedList集合類
- Queue<T> 先進先出的集合類
- Stack<T> 后進先出的集合類
- Collection<T> 自定義泛型集合的基類
- Dictionary<TKey, TValue> 對應于Hashtable集合類
原文鏈接:https://www.cnblogs.com/darrenji/p/3850445.html
相關推薦
- 2022-11-02 kotlin協程之coroutineScope函數使用詳解_Android
- 2022-05-17 Redis調用Lua腳本及使用場景快速掌握_Redis
- 2022-05-06 pyecharts的Tab和Legend布局詳情_python
- 2022-12-14 Flutter實現手勢識別功能詳解方法_Android
- 2022-11-04 Android自定義View實現時鐘功能_Android
- 2022-12-06 C++中調用復制(拷貝)函數的三種情況總結_C 語言
- 2022-03-29 Qt超時鎖屏的實現示例_C 語言
- 2024-07-18 Spring Security之基于HttpRequest配置權限
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支