標籤:color clone efault iso 引用 HERE where 方法 參考型別
轉自:http://www.cnblogs.com/kk888/archive/2011/09/01/2161647.html
所謂泛型,即通過參數化型別來實現在同一份代碼上操作多種資料類型。泛型程式設計是一種編程範式,它利用“參數化型別”將類型抽象化,從而實現更為靈活的複用。
在定義泛型類時,可以對用戶端代碼能夠在執行個體化類時用於型別參數的類型種類施加限制。如果用戶端代碼嘗試使用某個約束所不允許的類型來執行個體化類,則會產生編譯時間錯誤。這些限制稱為約束。約束是使用 where 內容關鍵字指定的。
下表列出了五種類型的約束:
約束 |
說明 |
T:struct |
型別參數必須是實值型別。可以指定除 Nullable 以外的任何實值型別。 |
T:class |
型別參數必須是參考型別,包括任何類、介面、委託或數群組類型。 |
T:new() |
型別參數必須具有無參數的公用建構函式。當與其他約束一起使用時,new() 約束必須最後指定。 |
T:<基類名> |
型別參數必須是指定的基類或派生自指定的基類。 |
T:<介面名稱> |
型別參數必須是指定的介面或實現指定的介面。可以指定多個介面約束。約束介面也可以是泛型的。 |
T:U |
為 T 提供的型別參數必須是為 U 提供的參數或派生自為 U 提供的參數。這稱為裸類型約束. |
---------------------------------------
一.派生約束
1.常見的
public class MyClass5<T> where T :IComparable { }
2.約束放在類的實際派生之後
public class B { } public class MyClass6<T> : B where T : IComparable { }
3.可以繼承一個基類和多個介面,且基類在介面前面
public class B { }
public class MyClass7<T> where T : B, IComparable, ICloneable { }
二.建構函式約束
1.常見的
public class MyClass8<T> where T : new() { }
2.可以將建構函式約束和派生約束組合起來,前提是建構函式約束出現在約束列表的最後
public class MyClass8<T> where T : IComparable, new() { }
三.值約束
1.常見的
public class MyClass9<T> where T : struct { }
2.與介面約束同時使用,在最前面(不能與基類約束,建構函式約束一起使用)
public class MyClass11<T> where T : struct, IComparable { }
四.參考條件約束
1.常見的
public class MyClass10<T> where T : class { }
五.多個泛型參數
public class MyClass12<T, U> where T : IComparable where U : class { }
六.繼承和泛型
public class B<T>{ }
1. 在從泛型基類派生時,可以提供類型實參,而不是基類泛型參數
public class SubClass11 : B<int> { }
2.如果子類是泛型,而非具體的類型實參,則可以使用子類泛型參數作為泛型基類的指定類型
public class SubClass12<R> : B<R> { }
3.在子類重複基類的約束(在使用子類泛型參數時,必須在子類層級重複在基類層級規定的任何約束)
public class B<T> where T : ISomeInterface { } public class SubClass2<T> : B<T> where T : ISomeInterface { }
4.建構函式約束
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泛型機制支援在"方法聲名上包含型別參數",這就是泛型方法)
1.泛型方法既可以包含在泛型型別中,又可以包含在非泛型型別中
public class MyClass5 { public void MyMethod<T>(T t){ } }
2.泛型方法的聲明與調用
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 MyMethod2<T>(int i){ } void MyMethod2(int i){ }
//第二組重載
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; } }
以下重載是錯誤的:
//第一組重載 void MyMethod1<T>(T t, int i){ } void MyMethod1<U>(U u, int i){ }//第二組重載,假設有兩個泛型參數 void MyMethod3<T>(T t) where T : A { }void MyMethod3<U>(U t) where T : 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) //不能重複任何約束 { } }(2)public class MyBaseClass2 { public virtual void MyMothed<T>(T t) { } } public class MySubClass2 : MyBaseClass2 { public override void MyMothed<T>(T t) //重新定義泛型參數T { } }
八.虛擬方法
public class BaseClass4<T> { public virtual T SomeMethod() { return default(T); } } public class SubClass4 : BaseClass4<int> //使用實參繼承的時候方法要使用實參的類型 { public override int SomeMethod() { return 0; } } public class SubClass5<T> : BaseClass4<T> //使用泛型繼承時,方法也是泛型 { public override T SomeMethod() { return default(T); } }
九.編譯器只允許將泛型參數隱式強制轉換到 Object 或約束指定的類型
class MyClass<T> where T : BaseClass, ISomeInterface { void SomeMethod(T t) { ISomeInterface obj1 = t; BaseClass obj2 = t; object obj3 = t; } }
變通方法:使用臨時的 Object 變數,將泛型參數強制轉換到其他任何類型
class MyClass2<T> { void SomeMethod(T t) { object temp = t; BaseClass obj = (BaseClass)temp; } }
十.編譯器允許您將泛型參數顯式強制轉換到其他任何介面,但不能將其轉換到類
class MyClass1<T> { void SomeMethod(T t) { ISomeInterface obj1 = (ISomeInterface)t; //BaseClass obj2 = (BaseClass)t; //不能通過編譯 } }
十一.使用臨時的 Object 變數,將泛型參數強制轉換到其他任何類型
class MyClass2<T> { void SomeMethod(T t) { object temp = t; BaseClass obj = (BaseClass)temp; } }
十二.使用is和as運算子
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) { } } }
【轉】C#泛型約束