ASP.NET泛型一之泛型簡(jiǎn)介與基本語(yǔ)法
".NET泛型"系列:
.NET泛型或許是借鑒于C++泛型模版,借助它可以實(shí)現(xiàn)對(duì)類(lèi)型的抽象化、泛型處理,實(shí)現(xiàn)了類(lèi)型和方法之間的解耦。一個(gè)最經(jīng)典的運(yùn)用是在三層架構(gòu)中,針對(duì)不同的領(lǐng)域模型,在基接口、基類(lèi)中實(shí)現(xiàn)針對(duì)各個(gè)領(lǐng)域模型的泛型處理。
為什么需要泛型
不用泛型
來(lái)看一個(gè)比較類(lèi)型的方法。
public class Calculator { public static bool AreEqual(int value1, int value2) { return value1 == value2; } }
在客戶(hù)端調(diào)用。
class Program { static void Main(string[] args) { bool result = Calculator.AreEqual(1, 2); if (result) { Console.WriteLine("相等"); } else { Console.WriteLine("不等"); } Console.ReadKey(); } }
運(yùn)行結(jié)果:不等
不用泛型的缺點(diǎn)一:不是類(lèi)型安全
如果我們想使用現(xiàn)在的方法來(lái)比較字符串類(lèi)型。
bool result = Calculator.AreEqual("A", "B");
這時(shí),看到編譯器報(bào)錯(cuò)。從這點(diǎn)來(lái)看,AreEqual()方法不是類(lèi)型安全的方法,當(dāng)輸入string類(lèi)型,編譯器就會(huì)報(bào)錯(cuò)。
如果把AreEqual()方法的參數(shù)類(lèi)型改成object,編譯器就不再報(bào)錯(cuò)。
public class Calculator { public static bool AreEqual(object value1, object value2) { return value1 == value2; } }
以上,運(yùn)行也正常。
不用泛型的缺點(diǎn)二:裝箱與拆箱導(dǎo)致性能降低
現(xiàn)在,對(duì)于AreEqual(object value1, object value2),從方法本身來(lái)講是沒(méi)有問(wèn)題的,但在客戶(hù)端調(diào)用的時(shí)候,比如我們還是想比較值類(lèi)型。
bool result = Calculator.AreEqual(1, 2);
在運(yùn)行時(shí),當(dāng)整型值類(lèi)型參數(shù)1和2傳遞、賦值給AreEqual(object value1, object value2)中的引用類(lèi)型參數(shù)value1和value2的時(shí)候,發(fā)生了一次"裝箱"操作。而當(dāng)把引用類(lèi)型轉(zhuǎn)換成值類(lèi)型的時(shí)候,又會(huì)發(fā)生一次"拆箱"操作,這導(dǎo)致性能的降低。
使用泛型
把AreEqual()改成泛型方法。
public class Calculator { public static bool AreEqual<T>(T value1, T value2) { return value1.Equals(value2); } }
于是,在客戶(hù)端可以這樣:
bool result = Calculator.AreEqual<string>("A", "A"); bool result = Calculator.AreEqual<int>(5, 3);
由此,使用泛型的好處有:
1、實(shí)現(xiàn)了方法和類(lèi)型的解耦。
2、不會(huì)造成類(lèi)型轉(zhuǎn)換,規(guī)避了因裝箱于拆箱引起的性能問(wèn)題。
3、泛型保證了類(lèi)型的絕對(duì)安全。
當(dāng)然,還可以把T的位置放在類(lèi)上:
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);
泛型的運(yùn)行時(shí)本質(zhì)
CLR中有專(zhuān)門(mén)的IL指令支持泛型操作。
→初次編譯時(shí),生成IL代碼和元數(shù)據(jù),T只是類(lèi)型占位符,在編譯時(shí)不進(jìn)行實(shí)例化
→JIT編譯時(shí),以實(shí)際類(lèi)型替換元數(shù)據(jù)中的T占位符
→將元數(shù)據(jù)轉(zhuǎn)換為本地代碼
泛型語(yǔ)法
class MyArray<T> where T : Student, new() { private T[] _items; public T myData; public MyArray() { myData = default(T); } public void Add(T item) {} }
創(chuàng)建泛型實(shí)例要指定實(shí)際的數(shù)據(jù)類(lèi)型:
MyArray<Int32> myArr = new MyArray<Int32>();
值類(lèi)型的默認(rèn)值為0,引用類(lèi)型的默認(rèn)值為null,使用泛型默認(rèn)值:
myData = default(T);
泛型約束:
- T : 基類(lèi)名,表示必須是基類(lèi)名的派生類(lèi)
- T :new(), 表示必須具有無(wú)參構(gòu)造函數(shù),new()約束必須放在最后面
- T :struct, 表示必須是值類(lèi)型
- T :class, 表示必須是引用類(lèi)型
- T :接口名,表示必須實(shí)現(xiàn)該接口,或?qū)崿F(xiàn)該接口的接口
泛型類(lèi)本質(zhì)上仍然是一個(gè)類(lèi),依然可以繼承:
internal class GenericeComparer<T> : Comparer<T> where T : IComparable<T> class MyArray<T> : ArrayList
典型的泛型類(lèi)
在System.Collections.Generic命名空間和System.Collections.ObjectModel中,定義了不同的泛型類(lèi)和泛型接口,這些泛型多為集合類(lèi)。
- List<T> 對(duì)應(yīng)ArrayList集合類(lèi)
- SortedList<TKey, TValue> 對(duì)應(yīng)SortedList集合類(lèi)
- Queue<T> 先進(jìn)先出的集合類(lèi)
- Stack<T> 后進(jìn)先出的集合類(lèi)
- Collection<T> 自定義泛型集合的基類(lèi)
- Dictionary<TKey, TValue> 對(duì)應(yīng)于Hashtable集合類(lèi)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章:
1. ASP.Net Core對(duì)USB攝像頭進(jìn)行截圖2. ASP.NET延遲調(diào)用或多次調(diào)用第三方Web API服務(wù)3. ASP.NET MVC獲取多級(jí)類(lèi)別組合下的產(chǎn)品4. ASP.NET Core依賴(lài)注入DI容器的方法實(shí)現(xiàn)5. asp.net web api2設(shè)置默認(rèn)啟動(dòng)登錄頁(yè)面的方法6. ASP.NET MVC使用Quartz.NET執(zhí)行定時(shí)任務(wù)7. ASP.NET Core整合Zipkin鏈路跟蹤的實(shí)現(xiàn)方法8. asp.net core應(yīng)用docke部署到centos7的全過(guò)程9. Asp.net Core項(xiàng)目配置HTTPS支持10. ASP.NET Core自定義中間件的方式詳解
