国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

《C#高級(jí)編程(第六版)》泛型學(xué)習(xí)筆記(一):泛型優(yōu)點(diǎn)和特性 (轉(zhuǎn)載)

2019-11-17 02:14:25
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

《C#高級(jí)編程(第六版)》泛型學(xué)習(xí)筆記(一):泛型優(yōu)點(diǎn)和特性 (轉(zhuǎn)載)

原文出處:http://www.survivalescaperooms.com/xun126/archive/2011/01/13/1933838.html

泛型是CLR 2.0的一個(gè)新特性,在CLR 1.0中,要?jiǎng)?chuàng)建一個(gè)靈活的類(lèi)或方法,但該類(lèi)或方法在編譯期間不知道使用什么類(lèi),就得以O(shè)bject類(lèi)為基礎(chǔ)。而Object在編譯期間沒(méi)有類(lèi)型安全性,因此必須進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換,同時(shí),給值類(lèi)型使用Object類(lèi)會(huì)有性能損失。泛型類(lèi)使用泛型類(lèi)型,并可以根據(jù)需要用特定的類(lèi)型替換泛型類(lèi)型。這就保證了類(lèi)型安全性:如果某個(gè)類(lèi)型不支持泛型類(lèi),編譯器就會(huì)報(bào)錯(cuò)。

  一、泛型有以下幾個(gè)優(yōu)點(diǎn):

  1)性能

  對(duì)值類(lèi)型使用非泛型集合類(lèi),在把值類(lèi)型轉(zhuǎn)換為引用類(lèi)型,和把引用類(lèi)型轉(zhuǎn)換為值類(lèi)型時(shí),需要進(jìn)行裝箱和拆箱操作。裝箱和拆箱的操作很容易實(shí)現(xiàn),但是性能損失較大。假如使用泛型,就可以避免裝箱和拆箱操作。

1 ArrayList list=new ArrayList(); 2 list.Add(20); //裝箱,list存放的是object類(lèi)型元素,須將值類(lèi)型轉(zhuǎn)化為引用類(lèi)型 3 int i=(int)list[0]; //拆箱,list[0]的類(lèi)型是object,要賦值就得把引用類(lèi)型轉(zhuǎn)化為值類(lèi)型

  如果換成泛型編程,就不會(huì)有裝箱和拆箱的性能損失。

1 List<T> list=new List<int>(); 2 list.Add(20); //因?yàn)橹付擞胕nt來(lái)實(shí)例化,因此不必裝箱 3 int i=list[0]; //同樣地,訪(fǎng)問(wèn)時(shí)也不需要拆箱

  

  2)類(lèi)型安全

  與ArrayList類(lèi)一樣,如果使用對(duì)象,可以在這個(gè)集合中添加任意類(lèi)型。

  如果使用非泛型編程,如下代碼,就有可能在某些情況下會(huì)發(fā)生異常。

復(fù)制代碼1 ArrayList list=new ArrayList(); 2 list.Add(20); 3 list.Add("string"); 4 list.Add(new MyClass()); 5 6 foreach(int i in list) 7 { 8 Console.WriteLine(i); //這里會(huì)有個(gè)異常,因?yàn)椴⒉皇羌现械乃性囟伎梢赞D(zhuǎn)化為int 9 }復(fù)制代碼

  如果該用泛型編程,則可以避免這種異常,讓編譯器檢查出錯(cuò)誤。

1 List<int> list=new List<int>(); 2 list.Add(20); 3 lsit.Add("string"); //編譯時(shí)報(bào)錯(cuò),只能報(bào)整數(shù)類(lèi)型添加到集合中 4 list.Add(new MyClass()); //同上

  

  3)二進(jìn)制代碼重用

  泛型可以定義一次,用許多不同的類(lèi)型實(shí)例化,不需要像C++模板那樣訪(fǎng)問(wèn)源代碼。泛型可以在一種語(yǔ)言中定義,在另一種.NET語(yǔ)言中使用。

  4)代碼的擴(kuò)展

  因?yàn)榉盒皖?lèi)的定義會(huì)放在程序集中,所以用某個(gè)類(lèi)型實(shí)例化泛型泛型類(lèi)不會(huì)在IL代碼中復(fù)制這些類(lèi)。但是,在JIT編譯器把泛型類(lèi)編譯為內(nèi)部代碼時(shí),會(huì)給每個(gè)值類(lèi)型創(chuàng)建一個(gè)新類(lèi)。引用類(lèi)型共享同一個(gè)內(nèi)部類(lèi)的所有實(shí)現(xiàn)代碼。這是因?yàn)橐妙?lèi)型在實(shí)例化的泛型類(lèi)中只需要4字節(jié)的內(nèi)存單元(32位系統(tǒng)),就可以引用一個(gè)引用類(lèi)型。值類(lèi)型包含在實(shí)例化的泛型類(lèi)的內(nèi)存中。而每個(gè)值類(lèi)型對(duì)內(nèi)存的要求都不同,所以要為每個(gè)值類(lèi)型實(shí)例化一個(gè)新類(lèi)。

  二、泛型類(lèi)的特性

  1)默認(rèn)值

在給類(lèi)型T初始化時(shí),要注意不能把null賦予泛型類(lèi)型。因?yàn)榉盒皖?lèi)型也可以實(shí)例化為值類(lèi)型,而null只能用于引用類(lèi)型。為了解決這個(gè)問(wèn)題,可以用default關(guān)鍵字。通過(guò)default關(guān)鍵字,將null賦予引用類(lèi)型,將0賦予值類(lèi)型。

復(fù)制代碼1 public T GetDoucumet() 2 { 3 T doc=default(T); 4 lock(this) 5 { 6 doc=documentQueue.Dequeue(); 7 } 8 return doc; 9 }復(fù)制代碼

補(bǔ)充:default關(guān)鍵字根據(jù)上下文可以有多種含義。switch語(yǔ)句使用default定義默認(rèn)情況。在泛型中,根據(jù)泛型類(lèi)型是引用類(lèi)型還是值類(lèi)型,default關(guān)鍵字用于將泛型類(lèi)型初始化為null或0。

  2)約束

  如果泛型類(lèi)需要調(diào)用泛型類(lèi)型上的方法,就必須添加約束。

復(fù)制代碼 1 public class DocumentManager<T> 2 { 3 PRivate readonly Queue<T> documentQueue=new Queue<T>(); 4 5 public void AddDocument(T doc) 6 { 7 lock(this) 8 { 9 documentQueue.Enqueue(doc); 10 } 11 } 12 13 public bool IsDocumentAvailable 14 { 15 get 16 { 17 return documentQueue.Count>0; 18 } 19 } 20 } 21 22 public interface IDocument 23 { 24 string Title{get;set;} 25 string Content{get;set;} 26 } 27 28 public class Document:IDocument 29 { 30 public Document() 31 { 32 } 33 34 public Document(string title,string content) 35 { 36 this.title=title; 37 this.content=content; 38 } 39 40 public string Title{get;set;} 41 public string Content{get;set;} 42 }復(fù)制代碼

  如果使用DocumentManager<T>類(lèi)顯示文檔,可以將類(lèi)型T強(qiáng)制轉(zhuǎn)換為IDocument接口

復(fù)制代碼1 public void DisplayAllDocument() 2 { 3 foreach(T doc in documentQueue) 4 { 5 Console.WriteLine(((IDocument)doc).Title); 6 } 7 }復(fù)制代碼

  假如類(lèi)型T沒(méi)有執(zhí)行IDocument接口,這個(gè)類(lèi)型轉(zhuǎn)換就會(huì)生成一個(gè)異常,因此需給DocumentManager<T>類(lèi)定義一個(gè)約束:T必須執(zhí)行IDocument接口,為了在泛型類(lèi)型的名稱(chēng)中指定該要求,將T改為T(mén)Document。wherer子句指定了執(zhí)行IDocument接口的要求。

1 public class DocumentManager<TDocument>where TDocument:IDocument 2 { 3 .... 4 }

  這樣編寫(xiě)foreach語(yǔ)句就可以讓類(lèi)型T包含Title屬性。

復(fù)制代碼1 public void DisplayAllDocument() 2 { 3 foreach(TDocument doc in documentQueue) 4 { 5 Console.WriteLine(doc.Title); 6 } 7 }復(fù)制代碼

  在Main()方法中,DocumentManager<T>類(lèi)用Document類(lèi)型來(lái)實(shí)例化,而Document類(lèi)型執(zhí)行了需要的IDocument接口。

1 static void Main() 2 { 3 DocumentManager<Document> dm=new DocumentManager<Document>(); 4 dm.AddDocument(new Document("Title A","A")); 5 dm.AddDocument(new Document("Title B","B")); 6 dm.DisplayAllDocument();

  除此之外,泛型還有幾種約束類(lèi)型。如下:

  1)where T:struct  使用結(jié)構(gòu)約束。類(lèi)型T必須是值類(lèi)型

  2)where T:class  類(lèi)約束指定,類(lèi)型T必須是引用類(lèi)型

  3)where T:IFoo  指定類(lèi)型T必須執(zhí)行接口IFoo

  4)where T:Foo  指定類(lèi)型T必須派生于基類(lèi)Foo

  5)where T:new()  構(gòu)造函數(shù)約束,指定類(lèi)型T必須有一個(gè)默認(rèn)構(gòu)造函數(shù)

  6)where T:U  類(lèi)型T1派生于泛型類(lèi)型T2。該約束也成為裸類(lèi)型約束。

  注意:使用泛型類(lèi)型還可以合并多個(gè)約束。where T:IFoo,new()約束和MyClass<T>聲明指定,類(lèi)型T必須執(zhí)行IFoo接口,且必須有一個(gè)默認(rèn)構(gòu)造函數(shù)。

1 public class MyClass<T>where t:IFoo,new() 2 { 3 ... 4 }

  

  3)繼承

  泛型類(lèi)型可以執(zhí)行泛型接口,也可以派生于一個(gè)類(lèi)。泛型類(lèi)可以派生于泛型基類(lèi):

復(fù)制代碼1 public class Base<T> 2 { 3 4 } 5 6 public class Derived<T>:Base<T> 7 { 8 9 }復(fù)制代碼

  要求必須重復(fù)接口的泛型類(lèi)型,或者必須指定基類(lèi)的類(lèi)型。

復(fù)制代碼1 public class Base<T> 2 { 3 4 } 5 6 public class Derived<T>:Base<string> 7 { 8 9 }復(fù)制代碼

  所以,派生類(lèi)可以是泛型類(lèi)或非泛型類(lèi)。如可以定義一個(gè)抽象的泛型基類(lèi),它在派生類(lèi)中用一個(gè)具體的類(lèi)型實(shí)現(xiàn)。

復(fù)制代碼 1 public abstract class Calc<T> 2 { 3 public abstract T Add(T x,T y); 4 public abstract T Sub(T x,T y); 5 } 6 7 public class SimpleCalc:Calc<int> 8 { 9 public override int Add(int x,int y) 10 { 11 return x+y; 12 } 13 14 public override int Sub(int x,int y) 15 { 16 return x-y; 17 } 18 }復(fù)制代碼

  4)靜態(tài)成員

  泛型類(lèi)的靜態(tài)成員需要特別關(guān)注。泛型類(lèi)的靜態(tài)成員只能在類(lèi)的一個(gè)實(shí)例中共享。

1 public class StaticDemo<T> 2 { 3 public static int x; 4 }

  對(duì)一個(gè)string類(lèi)型和一個(gè)int類(lèi)型使用了StaticDemo<T>類(lèi),所以存在兩組靜態(tài)字段:

1 StaticDemo<string>.x=4; 2 StaticDemo<int>.x=5; 3 Console.WrileLine(StaticDemo<string>.x); //將會(huì)輸出4
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 江孜县| 巴林右旗| 铁力市| 嵩明县| 南郑县| 荔波县| 珠海市| 农安县| 眉山市| 镇安县| 丹东市| 博乐市| 时尚| 河西区| 麦盖提县| 肇庆市| 乌拉特中旗| 呼伦贝尔市| 中江县| 新巴尔虎左旗| 和龙市| 乌兰察布市| 隆子县| 广水市| 永济市| 方正县| 潜山县| 沾化县| 盐边县| 大关县| 永福县| 长葛市| 仪征市| 绥化市| 吉隆县| 鸡西市| 新化县| 凭祥市| 曲靖市| 永川市| 石河子市|