C#泛型的使用及示例詳解_第1頁
C#泛型的使用及示例詳解_第2頁
C#泛型的使用及示例詳解_第3頁
C#泛型的使用及示例詳解_第4頁
C#泛型的使用及示例詳解_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第C#泛型的使用及示例詳解///paramname="tParameter"/param

publicstaticvoidShowT(TtParameter)whereT:People

Console.WriteLine($"{tParameter.Id}_{tParameter.Name}");

tParameter.Hi();

}

注意:

基類約束時,基類不能是密封類,即不能是sealed類。sealed類表示該類不能被繼承,在這里用作約束就無任何意義,因為sealed類沒有子類。

2、接口約束

///summary

///接口約束

////summary

///typeparamname="T"/typeparam

///paramname="t"/param

///returns/returns

publicstaticTGetT(Tt)whereT:ISports

t.Pingpang();

returnt;

}

3、引用類型約束class

引用類型約束保證T一定是引用類型的。

///summary

///引用類型約束

////summary

///typeparamname="T"/typeparam

///paramname="t"/param

///returns/returns

publicstaticTGetT(Tt)whereT:class

returnt;

}

4、值類型約束struct

值類型約束保證T一定是值類型的。

///summary

///值類型類型約束

////summary

///typeparamname="T"/typeparam

///paramname="t"/param

///returns/returns

publicstaticTGetT(Tt)whereT:struct

returnt;

}

5、無參數(shù)構(gòu)造函數(shù)約束new()

///summary

///new()約束

////summary

///typeparamname="T"/typeparam

///paramname="t"/param

///returns/returns

publicstaticTGetT(Tt)whereT:new()

returnt;

}

泛型約束也可以同時約束多個,例如:

publicstaticvoidShowT(TtParameter)

whereT:People,ISports,IWork,new()

Console.WriteLine($"{tParameter.Id}_{tParameter.Name}");

tParameter.Hi();

tParameter.Pingpang();

tParameter.Work();

}

注意:有多個泛型約束時,new()約束一定是在最后。

六、泛型的協(xié)變和逆變

協(xié)變和逆變是在.NET4.0的時候出現(xiàn)的,只能放在接口或者委托的泛型參數(shù)前面,out協(xié)變covariant,用來修飾返回值;in:逆變contravariant,用來修飾傳入?yún)?shù)。

先看下面的一個例子:

定義一個Animal類:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Threading.Tasks;

namespaceMyGeneric

publicclassAnimal

publicintId{get;set;}

}

然后在定義一個Cat類繼承自Animal類:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Threading.Tasks;

namespaceMyGeneric

publicclassCat:Animal

publicstringName{get;set;}

}

在Main()方法可以這樣調(diào)用:

//直接聲明Animal類

Animalanimal=newAnimal();

//直接聲明Cat類

Catcat=newCat();

//聲明子類對象指向父類

Animalanimal2=newCat();

//聲明Animal類的集合

ListAnimallistAnimal=newListAnimal

//聲明Cat類的集合

ListCatlistCat=newListCat

那么問題來了:下面的一句代碼是不是正確的呢?

ListAnimallist=newListCat

可能有人會認為是正確的:因為一只Cat屬于Animal,那么一群Cat也應(yīng)該屬于Animal啊。但是實際上這樣聲明是錯誤的:因為ListCat和ListAnimal之間沒有父子關(guān)系。

這時就可以用到協(xié)變和逆變了。

//協(xié)變

IEnumerableAnimalList1=newListAnimal

IEnumerableAnimalList2=newListCat

F12查看定義:

可以看到,在泛型接口的T前面有一個out關(guān)鍵字修飾,而且T只能是返回值類型,不能作為參數(shù)類型,這就是協(xié)變。使用了協(xié)變以后,左邊聲明的是基類,右邊可以聲明基類或者基類的子類。

協(xié)變除了可以用在接口上面,也可以用在委托上面:

FuncAnimalfunc=newFuncCat(()=null);

除了使用.NET框架定義好的以為,我們還可以自定義協(xié)變,例如:

///summary

///out協(xié)變只能是返回結(jié)果

////summary

///typeparamname="T"/typeparam

publicinterfaceICustomerListOutoutT

TGet();

publicclassCustomerListOutT:ICustomerListOutT

publicTGet()

returndefault(T);

}

使用自定義的協(xié)變:

//使用自定義協(xié)變

ICustomerListOutAnimalcustomerList1=newCustomerListOutAnimal

ICustomerListOutAnimalcustomerList2=newCustomerListOutCat

在來看看逆變。

在泛型接口的T前面有一個In關(guān)鍵字修飾,而且T只能方法參數(shù),不能作為返回值類型,這就是逆變。請看下面的自定義逆變:

///summary

///逆變只能是方法參數(shù)

////summary

///typeparamname="T"/typeparam

publicinterfaceICustomerListIninT

voidShow(Tt);

publicclassCustomerListInT:ICustomerListInT

publicvoidShow(Tt)

}

使用自定義逆變:

//使用自定義逆變

ICustomerListInCatcustomerListCat1=newCustomerListInCat

ICustomerListInCatcustomerListCat2=newCustomerListInAnimal

協(xié)變和逆變也可以同時使用,看看下面的例子:

///summary

///inT逆變

///outT協(xié)變

////summary

///typeparamname="inT"/typeparam

///typeparamname="outT"/typeparam

publicinterfaceIMyListininT,outoutT

voidShow(inTt);

outTGet();

outTDo(inTt);

publicclassMyListT1,T2:IMyListT1,T2

publicvoidShow(T1t)

Console.WriteLine(t.GetType().Name);

publicT2Get()

Console.WriteLine(typeof(T2).Name);

returndefault(T2);

publicT2Do(T1t)

Console.WriteLine(t.GetType().Name);

Console.WriteLine(typeof(T2).Name);

returndefault(T2);

}

使用:

IMyListCat,AnimalmyList1=newMyListCat,Animal

IMyListCat,AnimalmyList2=newMyListCat,Cat//協(xié)變

IMyListCat,AnimalmyList3=newMyListAnimal,Animal//逆變

IMyListCat,AnimalmyList4=newMyListAnimal,Cat//逆變+協(xié)變

七、泛型緩存

在前面我們學習過,類中的靜態(tài)類型無論實例化多少次,在內(nèi)存中只會有一個。靜態(tài)構(gòu)造函數(shù)只會執(zhí)行一次。在泛型類中,T類型不同,每個不同的T類型,都會產(chǎn)生一個不同的副本,所以會產(chǎn)生不同的靜態(tài)屬性、不同的靜態(tài)構(gòu)造函數(shù),請看下面的例子:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Threading.Tasks;

namespaceMyGeneric

publicclassGenericCacheT

staticGenericCache()

Console.WriteLine("ThisisGenericCache靜態(tài)構(gòu)造函數(shù)");

_TypeTime=string.Format("{0}_{1}",typeof(T).FullName,DateTime.Now.ToString("yyyyMMddHHmmss.fff"));

privatestaticstring_TypeTime="";

publicstaticstringGetCache()

return_TypeTime;

}

然后新建一個測試類,用來測試GenericCache類的執(zhí)行順序:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Threading;

usingSystem.Threading.Tasks;

namespaceMyGeneric

publicclassGenericCacheTest

publicstaticvoidShow()

for(inti=0;ii++)

Console.WriteLine(GenericCacheint.GetCache());

Thread.Sleep(10);

Console.WriteLine(GenericCachelong.GetCache());

Thread.Sleep(10);

Console.WriteLine(GenericCacheDateTime.GetCache());

Thread.Sleep(10);

Console.WriteLine(GenericCachestring.GetCache());

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論