淡谈泛型约束T(转)
.net泛型約束??
2007-10-06 14:08:54|??分類: .net |字號(hào)?訂閱
所謂泛型,即通過(guò)參數(shù)化類型來(lái)實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型。泛型編程是一種編程范式,它利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)更為靈活的復(fù)用。
在定義泛型類時(shí),可以對(duì)客戶端代碼能夠在實(shí)例化類時(shí)用于類型參數(shù)的類型種類施加限制。如果客戶端代碼嘗試使用某個(gè)約束所不允許的類型來(lái)實(shí)例化類,則會(huì)產(chǎn)生編譯時(shí)錯(cuò)誤。這些限制稱為約束。約束是使用 where 上下文關(guān)鍵字指定的。
下表列出了五種類型的約束:
| T:struct | 類型參數(shù)必須是值類型。可以指定除 Nullable 以外的任何值類型。 |
| T:class | 類型參數(shù)必須是引用類型,包括任何類、接口、委托或數(shù)組類型。 |
| T:new() | 類型參數(shù)必須具有無(wú)參數(shù)的公共構(gòu)造函數(shù)。當(dāng)與其他約束一起使用時(shí),new() 約束必須最后指定。 |
| T:<基類名> | 類型參數(shù)必須是指定的基類或派生自指定的基類。 |
| T:<接口名稱> | 類型參數(shù)必須是指定的接口或?qū)崿F(xiàn)指定的接口。可以指定多個(gè)接口約束。約束接口也可以是泛型的。 |
| T:U | 為 T 提供的類型參數(shù)必須是為 U 提供的參數(shù)或派生自為 U 提供的參數(shù)。這稱為裸類型約束. |
?---------------------------------------
一.派生約束
1.常見的
public class MyClass5<T> where T :IComparable { }
2.約束放在類的實(shí)際派生之后
public class B { }
public class MyClass6<T> : B where T : IComparable { }
3.可以繼承一個(gè)基類和多個(gè)接口,且基類在接口前面
public class B { }
public class MyClass7<T> where T : B, IComparable, ICloneable { }
二.構(gòu)造函數(shù)約束
1.常見的
public class MyClass8<T> where T :? new() { }
2.可以將構(gòu)造函數(shù)約束和派生約束組合起來(lái),前提是構(gòu)造函數(shù)約束出現(xiàn)在約束列表的最后
public class MyClass8<T> where T : IComparable, new() { }
三.值約束
1.常見的
public class MyClass9<T> where T : struct { }
2.與接口約束同時(shí)使用,在最前面(不能與基類約束,構(gòu)造函數(shù)約束一起使用)
public class MyClass11<T> where T : struct, IComparable { }
四.引用約束
1.常見的
public class MyClass10<T> where T : class { }
五.多個(gè)泛型參數(shù)
?public class MyClass12<T, U> where T : IComparable? where U : class { }
六.繼承和泛型
public class B<T>{ }
1. 在從泛型基類派生時(shí),可以提供類型實(shí)參,而不是基類泛型參數(shù)
??? public class SubClass11 : B<int>
??? { }
2.如果子類是泛型,而非具體的類型實(shí)參,則可以使用子類泛型參數(shù)作為泛型基類的指定類型
??? public class SubClass12<R> : B<R>
??? { }
3.在子類重復(fù)基類的約束(在使用子類泛型參數(shù)時(shí),必須在子類級(jí)別重復(fù)在基類級(jí)別規(guī)定的任何約束)
??? public class B<T> where T : ISomeInterface { }
??? public class SubClass2<T> : B<T> where T : ISomeInterface { }
4.構(gòu)造函數(shù)約束
??? public class B<T> where T : new()
??? {
??????? public T SomeMethod()
??????? {
??????????? return new T();
??????? }
??? }
??? public class SubClass3<T> : B<T> where T : new(){ }
七.泛型方法(C#2.0泛型機(jī)制支持在"方法聲名上包含類型參數(shù)",這就是泛型方法)
1.泛型方法既可以包含在泛型類型中,又可以包含在非泛型類型中
public class MyClass5
??? {
??????? public void MyMethod<T>(T t){ }
??? }
2.泛型方法的聲明與調(diào)用
public class MyClass5
??? {
??????? public void MyMethod<T>(T t){ }
??? }
??? public class App5
??? {
??????? public void CallMethod()
??????? {
??????????? MyClass5 myclass5 = new MyClass5();
??????????? myclass5.MyMethod<int>(3);
??????? }
??? }
3.泛型方法的重載
?//第一組重載
?void MyMethod1<T>(T t, int i){ }
?void MyMethod1<U>(U u, int i){ }
//第二組重載
?void MyMethod2<T>(int i){ }
?void MyMethod2(int i){ }
//第三組重載,假設(shè)有兩個(gè)泛型參數(shù)
?void MyMethod3<T>(T t) where T : A { }
void MyMethod3<T>(T t) where T : B { }
//第四組重載
public class MyClass8<T,U>
??? {
??????? public T MyMothed(T a, U b)
??????? {
??????????? return a;
??????? }
??????? public T MyMothed(U a, T b)
??????? {
??????????? return b;
??????? }
??????? public int MyMothed(int a, int b)
??????? {
??????????? return a + b;
??????? }
??? }
4.泛型方法的覆寫
(1)public class MyBaseClass1
??? {
??????? public virtual void MyMothed<T>(T t) where T : new() { }
??? }
??? public class MySubClass1:MyBaseClass1
??? {
??????? public override void MyMothed<T>(T t) //不能重復(fù)任何約束
??????? { }
??? }
(2)public class MyBaseClass2
??? {
??????? public virtual void MyMothed<T>(T t)
??????? { }
??? }
??? public class MySubClass2 : MyBaseClass2
??? {
??????? public override void MyMothed<T>(T t) //重新定義泛型參數(shù)T
??????? { }
??? }
八.虛擬方法
public class BaseClass4<T>
??? {
??????? public virtual T SomeMethod()
??????? {
??????????? return default(T);
??????? }
??? }
??? public class SubClass4 : BaseClass4<int> //使用實(shí)參繼承的時(shí)候方法要使用實(shí)參的類型
??? {
??????? public override int SomeMethod()
??????? {
??????????? return 0;
??????? }
??? }
??? public class SubClass5<T> : BaseClass4<T> //使用泛型繼承時(shí),方法也是泛型
??? {
??????? public override T SomeMethod()
??????? {
??????????? return default(T);
??????? }
??? }
九.編譯器只允許將泛型參數(shù)隱式強(qiáng)制轉(zhuǎn)換到 Object 或約束指定的類型
class MyClass<T> where T : BaseClass, ISomeInterface
??? {
??????? void SomeMethod(T t)
??????? {
??????????? ISomeInterface obj1 = t;
??????????? BaseClass obj2 = t;
??????????? object obj3 = t;
??????? }
??? }
變通方法:使用臨時(shí)的 Object 變量,將泛型參數(shù)強(qiáng)制轉(zhuǎn)換到其他任何類型
class MyClass2<T>
??? {
??????? void SomeMethod(T t)
??????? {
??????????? object temp = t;
??????????? BaseClass obj = (BaseClass)temp;
??????? }
??? }
十.編譯器允許您將泛型參數(shù)顯式強(qiáng)制轉(zhuǎn)換到其他任何接口,但不能將其轉(zhuǎn)換到類
class MyClass1<T>
??? {
??????? void SomeMethod(T t)
??????? {
??????????? ISomeInterface obj1 = (ISomeInterface)t;?
??????????? //BaseClass obj2 = (BaseClass)t;?????????? //不能通過(guò)編譯
??????? }
??? }
?
十一.使用臨時(shí)的 Object 變量,將泛型參數(shù)強(qiáng)制轉(zhuǎn)換到其他任何類型
class MyClass2<T>
??? {
??????? void SomeMethod(T t)
??????? {
??????????? object temp = t;
??????????? BaseClass obj = (BaseClass)temp;
??????? }
??? }
十二.使用is和as運(yùn)算符
public class MyClass3<T>
??? {
??????? public void SomeMethod(T t)
??????? {
??????????? if (t is int) { }
??????????? if (t is LinkedList<int>) { }
??????????? string str = t as string;
??????????? if (str != null) { }
??????????? LinkedList<int> list = t as LinkedList<int>;
??????????? if (list != null) { }
??????? }
??? }
轉(zhuǎn)載于:https://www.cnblogs.com/kk888/archive/2011/09/01/2161647.html
總結(jié)
以上是生活随笔為你收集整理的淡谈泛型约束T(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 常见虚拟主机目录对照及星外提权目录
- 下一篇: 第二章 第三节 创建第一个程序