日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# 泛型编程学习总结

發(fā)布時(shí)間:2025/4/14 C# 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 泛型编程学习总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

C#泛型編程

http://www.cnblogs.com/kid-li/archive/2006/11/29/577045.html

? ? ? ?泛型:通過參數(shù)化類型來實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型。利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)靈活的復(fù)用。

例子代碼:

class Program{static void Main(string[] args){int obj = 2;Test<int> test = new Test<int>(obj);Console.WriteLine("int:" + test.obj);string obj2 = "hello world";Test<string> test1 = new Test<string>(obj2);Console.WriteLine("String:" + test1.obj);Console.Read();}}class Test<T>{public T obj;public Test(T obj){this.obj = obj;} }


? ? 輸出結(jié)果是:
? ? int:2
String:hello world
?
程序分析:
1、 ?Test是一個(gè)泛型類。T是要實(shí)例化的范型類型。如果T被實(shí)例化為int型,那么成員變量obj就是int型的,如果T被實(shí)例化為string型,那么obj就是string類型的。
2、 ?根據(jù)不同的類型,上面的程序顯示出不同的值。
?
C#泛型機(jī)制:
C#泛型能力有CLR在運(yùn)行時(shí)支持:C#泛型代碼在編譯為IL代碼和元數(shù)據(jù)時(shí),采用特殊的占位符來表示范型類型,并用專有的IL指令支持泛型操作。而真正的泛型實(shí)例化工作以“on-demand”的方式,發(fā)生在JIT編譯時(shí)。
?
看看剛才的代碼中Main函數(shù)的元數(shù)據(jù)
.method private hidebysig static void Main(string[] args) cil managed {.entrypoint// Code size 79 (0x4f).maxstack 2.locals init ([0] int32 obj,[1] class CSharpStudy1.Test`1<int32> test,[2] string obj2,[3] class CSharpStudy1.Test`1<string> test1)IL_0000: nopIL_0001: ldc.i4.2IL_0002: stloc.0IL_0003: ldloc.0IL_0004: newobj instance void class CSharpStudy1.Test`1<int32>::.ctor(!0)IL_0009: stloc.1IL_000a: ldstr "int:"IL_000f: ldloc.1IL_0010: ldfld !0 class CSharpStudy1.Test`1<int32>::objIL_0015: box [mscorlib]System.Int32IL_001a: call string [mscorlib]System.String::Concat(object,object)IL_001f: call void [mscorlib]System.Console::WriteLine(string)IL_0024: nopIL_0025: ldstr "hello world"IL_002a: stloc.2IL_002b: ldloc.2IL_002c: newobj instance void class CSharpStudy1.Test`1<string>::.ctor(!0)IL_0031: stloc.3IL_0032: ldstr "String:"IL_0037: ldloc.3IL_0038: ldfld !0 class CSharpStudy1.Test`1<string>::objIL_003d: call string [mscorlib]System.String::Concat(string,string)IL_0042: call void [mscorlib]System.Console::WriteLine(string)IL_0047: nopIL_0048: call int32 [mscorlib]System.Console::Read()IL_004d: popIL_004e: ret } // end of method Program::Main
再來看看Test類中構(gòu)造函數(shù)的元數(shù)據(jù)
.method public hidebysig specialname rtspecialnameinstance void .ctor(!T obj) cil managed {// Code size 17 (0x11).maxstack 8IL_0000: ldarg.0IL_0001: call instance void [mscorlib]System.Object::.ctor()IL_0006: nopIL_0007: nopIL_0008: ldarg.0IL_0009: ldarg.1IL_000a: stfld !0 class ConsoleCSharpTest1.Test`1<!T>::objIL_000f: nopIL_0010: ret } // end of method Test`1::.ctor
1、第一輪編譯時(shí),編譯器只為Test<T>類型產(chǎn)生“泛型版”的IL代碼與元數(shù)據(jù)——并不進(jìn)行泛型的實(shí)例化,T在中間只充當(dāng)占位符。例如:Test類型元數(shù)據(jù)中顯示的<!T>
2、JIT編譯時(shí),當(dāng)JIT編譯器第一次遇到Test<int>時(shí),將用int替換“范型版”IL代碼與元數(shù)據(jù)中的T——進(jìn)行泛型類型的實(shí)例化。例如:Main函數(shù)中顯示的<int>
3、CLR為所有類型參數(shù)為“引用類型”的泛型類型產(chǎn)生同一份代碼;但是如果類型參數(shù)為“值類型”,對每一個(gè)不同的“值類型”,CLR將為其產(chǎn)生一份獨(dú)立的代碼。因?yàn)閷?shí)例化一個(gè)引用類型的泛型,它在內(nèi)存中分配的大小是一樣的,但是當(dāng)實(shí)例化一個(gè)值類型的時(shí)候,在內(nèi)存中分配的大小是不一樣的。
?
C#泛型特點(diǎn):
1、如果實(shí)例化泛型類型的參數(shù)相同,那么JIT編輯器會重復(fù)使用該類型,因此C#的動態(tài)泛型能力避免了C++靜態(tài)模板可能導(dǎo)致的代碼膨脹的問題。
2、C#泛型類型攜帶有豐富的元數(shù)據(jù),因此C#的泛型類型可以應(yīng)用于強(qiáng)大的反射技術(shù)。
3、C#的泛型采用“基類、接口、構(gòu)造器,值類型/引用類型”的約束方式來實(shí)現(xiàn)對類型參數(shù)的“顯示約束”,提高了類型安全的同時(shí),也喪失了C++模板基于“簽名”的隱式約束所具有的高靈活性
?
C#泛型繼承:
C#除了可以單獨(dú)聲明泛型類型(包括類與結(jié)構(gòu))外,也可以在基類中包含泛型類型的聲明。但基類如果是泛型類,它的類型要么以實(shí)例化,要么來源于子類(同樣是泛型類型)聲明的類型參數(shù),看如下類型
class C<U,V>
class D:C<string,int>
class E<U,V>:C<U,V>
class F<U,V>:C<string,int>
class G:C<U,V> ?//非法
E類型為C類型提供了U、V,也就是上面說的來源于子類
F類型繼承于C<string,int>,個(gè)人認(rèn)為可以看成F繼承一個(gè)非泛型的類
G類型為非法的,因?yàn)镚類型不是泛型,C是泛型,G無法給C提供泛型的實(shí)例化
?
泛型類型的成員:
泛型類型的成員可以使用泛型類型聲明中的類型參數(shù)。但類型參數(shù)如果沒有任何約束,則只能在該類型上使用從System.Object繼承的公有成員。如下圖:
?
泛型接口:
泛型接口的類型參數(shù)要么已實(shí)例化,要么來源于實(shí)現(xiàn)類聲明的類型參數(shù)
?
泛型委托:
泛型委托支持在委托返回值和參數(shù)上應(yīng)用參數(shù)類型,這些參數(shù)類型同樣可以附帶合法的約束
delegate bool MyDelegate<T>(T value); class MyClass {static bool F(int i){...}static bool G(string s){...}static void Main(){MyDelegate<string> p2 = G;MyDelegate<int> p1 = new MyDelegate<int>(F);} }

?泛型方法:
1、C#泛型機(jī)制只支持“在方法聲明上包含類型參數(shù)”——即泛型方法。
2、C#泛型機(jī)制不支持在除方法外的其他成員(包括屬性、事件、索引器、構(gòu)造器、析構(gòu)器)的聲明上包含類型參數(shù),但這些成員本身可以包含在泛型類型中,并使用泛型類型的類型參數(shù)。
3、泛型方法既可以包含在泛型類型中,也可以包含在非泛型類型中。
?
泛型方法聲明:如下
public static int FunctionName<T>(T value){...}
?
泛型方法的重載:
public void Function1<T>(T a);
public void Function1<U>(U a);
這樣是不能構(gòu)成泛型方法的重載。因?yàn)榫幾g器無法確定泛型類型T和U是否不同,也就無法確定這兩個(gè)方法是否不同
?
public void Function1<T>(int x);
public void Function1(int x);
這樣可以構(gòu)成重載
?
public void Function1<T>(T t) where T:A;
public void Function1<T>(T t) where T:B;
這樣不能構(gòu)成泛型方法的重載。因?yàn)榫幾g器無法確定約束條件中的A和B是否不同,也就無法確定這兩個(gè)方法是否不同
?
泛型方法重寫:
在重寫的過程中,抽象類中的抽象方法的約束是被默認(rèn)繼承的。如下:
abstract class Base
{
? ? public abstract T F<T,U>(T t,U u) where U:T;
? ? public abstract T G<T>(T t) where T:IComparable;
}
?
class MyClass:Base
{
? ? public override X F<X,Y>(X x,Y y){...}
? ? public override T G<T>(T t) where T:IComparable{}
}
對于MyClass中兩個(gè)重寫的方法來說
F方法是合法的,約束被默認(rèn)繼承
G方法是非法的,指定任何約束都是多余的
?
泛型約束:
1、C#泛型要求對“所有泛型類型或泛型方法的類型參數(shù)”的任何假定,都要基于“顯式的約束”,以維護(hù)C#所要求的類型安全。
2、“顯式約束”由where子句表達(dá),可以指定“基類約束”,“接口約束”,“構(gòu)造器約束”,“值類型/引用類型約束”共四種約束。
3、“顯式約束”并非必須,如果沒有指定“顯式約束”,范型類型參數(shù)將只能訪問System.Object類型中的公有方法。例如:在開始的例子中,定義的那個(gè)obj成員變量。比如我們在開始的那個(gè)例子中加入一個(gè)Test1類,在它當(dāng)中定義兩個(gè)公共方法Func1、Func2,如下圖:
?
下面就開始分析這些約束:
?
基類約束:
class A{public void Func1(){ }}class B{public void Func2(){ }}class C<S, T>where S : Awhere T : B{public C(S s,T t){//S的變量可以調(diào)用Func1方法s.Func1();//T的變量可以調(diào)用Func2方法t.Func2();}}
接口約束:
interface IA<T>{T Func1();}interface IB{void Func2();}interface IC<T>{T Func3();}class MyClass<T, V>where T : IA<T>where V : IB, IC<V>{public MyClass(T t,V v){//T的對象可以調(diào)用Func1t.Func1();//V的對象可以調(diào)用Func2和Func3v.Func2();v.Func3();}}

構(gòu)造器約束:

class A{public A(){ }}class B{public B(int i){ }}class C<T> where T : new(){T t;public C(){t = new T();}}class D{public void Func(){C<A> c = new C<A>();C<B> d = new C<B>();}}


? ? d對象在編譯時(shí)報(bào)錯(cuò):The type B must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method C<T>
? ? 注意:C#現(xiàn)在只支持無參的構(gòu)造器約束
? ? 此時(shí)由于我們?yōu)锽類型寫入了一個(gè)有參構(gòu)造器,使得系統(tǒng)不會再為B自動創(chuàng)建一個(gè)無參的構(gòu)造器,但是如果我們將B類型中加一個(gè)無參構(gòu)造器,那么對象d的實(shí)例化就不會報(bào)錯(cuò)了。B類型定義如下:
? ? ? ? class B
? ? ? ? {
? ? ? ? ? ? public B()
? ? ? ? ? ? { }
? ? ? ? ? ? public B(int i)
? ? ? ? ? ? { }

? ? ? ? }


值類型/引用類型:
public struct A { }
? ? ? ? public class B { }
?
? ? ? ? public class C<T> where T : struct
? ? ? ? {
?
? ? ? ? }
?
? ? ? ? C<A> c1 = new C<A>();
? ? ? ? C<B> c2 = new C<B>();
? ? c2對象在編譯時(shí)報(bào)錯(cuò):The type 'B' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or methor 'C<T>'
? ?
總結(jié):
1、C#的泛型能力由CLR在運(yùn)行時(shí)支持,它既不同于C++在編譯時(shí)所支持的靜態(tài)模板,也不同于Java在編譯器層面使用“擦拭法”支持的簡單的泛型。
2、C#的泛型支持包括類、結(jié)構(gòu)、接口、委托四種泛型類型,以及方法成員。
3、C#的泛型采用“基類,接口,構(gòu)造器,值類型/引用類型”的約束方式來實(shí)現(xiàn)對類型參數(shù)的“顯式約束”,它不支持C++模板那樣的基于簽名的隱式約束。
========

C# 泛型編程之泛型類、泛型方法、泛型約束

http://www.cnblogs.com/arxive/p/6179972.html 


  所謂泛型,即通過參數(shù)化類型來實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型。


  泛型編程是一種編程范式,它利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)更為靈活的復(fù)用。在定義泛型類時(shí),在對客戶端代碼能夠在實(shí)例化類時(shí),可以用類型參數(shù)的類型種類施加限制。


泛型方法
在C# 2.0中,方法可以定義特定于其執(zhí)行范圍的泛型參數(shù),如下所示:
復(fù)制代碼
public class MyClass<T>
{
? ? //指定MyMethod方法用以執(zhí)行類型為X的參數(shù)
? ? public void MyMethod<X>(X x)?
? ? {
? ? ? ? //
? ? }


? ? //此方法也可不指定方法參數(shù)
? ? public void MyMethod<X>()?
? ? {
? ? ? ? //
? ? }
} ??
復(fù)制代碼
即使包含類不適用泛型參數(shù),你也可以定義方法特定的泛型參數(shù),如下所示:


復(fù)制代碼
public class MyClass
{
? ? //指定MyMethod方法用以執(zhí)行類型為X的參數(shù)
? ? public void MyMethod<X>(X x)?
? ? {
? ? ? ? //
? ? }


? ? //此方法也可不指定方法參數(shù)
? ? public void MyMethod<X>()?
? ? {
? ? ? ? //
? ? }
}
復(fù)制代碼
注意:屬性和索引器不能指定自己的泛型參數(shù),它們只能使用所屬類中定義的泛型參數(shù)進(jìn)行操作。


在調(diào)用泛型方法的時(shí)候,你可以提供要在調(diào)用場所使用的類型,如下所示:


//調(diào)用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod<int>(3);
?
泛型推理:
在調(diào)用泛型方法時(shí),C#編譯器足夠聰明,基于傳入的參數(shù)類型來推斷出正確的類型,并且它允許完全省略類型規(guī)范,如下所示:
//泛型推理機(jī)制調(diào)用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3);


注意:泛型方法無法只根據(jù)返回值的類型推斷出類型,代碼如下:


復(fù)制代碼
public GenericMethodDemo()
{ ? ? ? ?
? ? MyClass myClass = new MyClass();
? ? /****************************************************
? ? 無法從用法中推理出方法“GenericMethodDemo.MyClass.MyMethod<T>()”的類型參數(shù)。
? ? 請嘗試顯式指定類型參數(shù)。
? ? ***************************************************/
? ? int number = myClass.MyMethod();
}


public class MyClass
{
? ? public T MyMethod<T>()?
? ? {
? ? ? ? //
? ? }
}
復(fù)制代碼
泛型方法中泛型參數(shù)的約束,如下:


復(fù)制代碼
public class MyClass
{
? ??
? ? public void MyMethod<X>(X x) where X:IComparable<X>
? ? {
? ? ? ? //
? ? }
}
復(fù)制代碼
泛型類
無法為類級別的泛型參數(shù)提供方法級別的約束。類級別泛型參數(shù)的所有約束都必須在類作用范圍中定義,代碼如下所示


復(fù)制代碼
public class MyClass<T>
{
? ??
? ? public void MyMethod<X>(X x,T t) where X:IComparable<X> where T:IComparer<T>
? ? {
? ? ? ? //
? ? }
}
復(fù)制代碼
而下面的代碼是正確的:


復(fù)制代碼
public class MyClass<T> where T:IComparable<T>
{
? ??
? ? public void MyMethod<X>(X x,T t) where X:IComparable<X>?
? ? {
? ? ? ? //
? ? }
}
復(fù)制代碼
泛型參數(shù)虛方法的重寫:子類方法必須重新定義該方法特定的泛型參數(shù),代碼如下


復(fù)制代碼
public class MyBaseClass
{
? ? public virtual void SomeMethod<T>(T t)
? ? {
? ? ? ? //
? ? }
}
public class MyClass :MyBaseClass
{
? ? public override void SomeMethod<X>(X x)
? ? {
? ? ? ??
? ? }
}
復(fù)制代碼
同時(shí)子類中的泛型方法不能重復(fù)基類泛型方法的約束,這一點(diǎn)和泛型類中的虛方法重寫是有區(qū)別的,代碼如下


復(fù)制代碼
public class MyBaseClass
{
? ? public virtual void SomeMethod<T>(T t) where T:new()
? ? {
? ? ? ? //
? ? }
}
public class MyClass :MyBaseClass
{
? ? //正確寫法
? ? public override void SomeMethod<X>(X x)
? ? {
? ? ? ??
? ? }


? ? 錯(cuò)誤 重寫和顯式接口實(shí)現(xiàn)方法的約束是從基方法繼承的,因此不能直接指定這些約束
? ? //public override void SomeMethod<X>(X x) where X:new()
? ? //{


? ? //}
}
復(fù)制代碼
?


子類方法調(diào)用虛擬方法的基類實(shí)現(xiàn):它必須指定要代替泛型基礎(chǔ)方法類型所使用的類型實(shí)參。你可以自己顯式的指定它,也可以依靠類型推理(如果可能的話)代碼如下:


復(fù)制代碼
public class MyBaseClass
{
? ? public virtual void SomeMethod<T>(T t) where T:new()
? ? {
? ? ? ? //
? ? }
}
public class MyClass :MyBaseClass
{
? ? //正確寫法
? ? public override void SomeMethod<X>(X x)
? ? {
? ? ? ? base.SomeMethod<X>(x);
? ? ? ? base.SomeMethod(x);
? ? }
}
復(fù)制代碼


泛型委托
在某個(gè)類中定義的委托可以使用該類的泛型參數(shù),代碼如下


復(fù)制代碼
public class MyClass<T>
{
? ? public delegate void GenericDelegate(T t);
? ? public void SomeMethod(T t)
? ? {
?
? ? }
}
public GenericMethodDemo()
{
? ? MyClass<int> obj = new MyClass<int>();
? ? MyClass<int>.GenericDelegate del;
? ? del = new MyClass<int>.GenericDelegate(obj.SomeMethod);
? ? del(3);
}
復(fù)制代碼?


委托推理:C#2.0使你可以將方法引用的直接分配轉(zhuǎn)變?yōu)槲凶兞俊⑸厦娴拇a改造如下


復(fù)制代碼
public class MyClass<T>
{
? ? public delegate void GenericDelegate(T t);
? ? public void SomeMethod(T t)
? ? {
?
? ? }
}
public GenericMethodDemo()
{
? ? MyClass<int> obj = new MyClass<int>();
? ? MyClass<int>.GenericDelegate del;


? ? //委托推理
? del = obj.SomeMethod;
? ? del(3);
?} ?
復(fù)制代碼
泛型委托的約束:


委托級別的約束只在聲明委托變量和實(shí)例化委托時(shí)使用,類似于在類型和方法的作用范圍中實(shí)施的其他任何約束。


泛型和反射


在Net2.0當(dāng)中,擴(kuò)展了反射以支持泛型參數(shù)。類型Type現(xiàn)在可以表示帶有特定類型的實(shí)參(或綁定類型)或未指定類型的泛型(或稱未綁定類型)。像C#1.1中那樣,您可以通過使用typeof運(yùn)算符或通過調(diào)用每個(gè)類型支持的GetType()來獲得任何類型的Type。代碼如下:


復(fù)制代碼
LinkedList<int> list = new LinkedList<int>();
?Type type1 = typeof(LinkedList<int>);
?Type type2 = list.GetType();
?Response.Write(type1 == type2);
?typeof和GetType()也可以對泛型參數(shù)進(jìn)行操作,如下


public class MyClass<T>
{
public void SomeMethod(T t)
{
? ? Type type = typeof(T);
? ? HttpContext.Current.Response.Write(type==t.GetType());
}
}
復(fù)制代碼
typeof還可以對未綁定的泛型進(jìn)行操作,代碼如下


復(fù)制代碼
protected void Page_Load(object sender, EventArgs e)
{
? ? if (!IsPostBack)
? ? {
? ? ? ? Type unboundType = typeof(MyClass<>);
? ? ? ? Response.Write(unboundType.ToString());
? ? }
}


public class MyClass<T>
{
? ? public void SomeMethod(T t)
? ? {
? ? ? ? Type type = typeof(T);
? ? ? ? HttpContext.Current.Response.Write(type==t.GetType());
? ? }
}
復(fù)制代碼
?


請注意"<>"的用法。要對帶有多個(gè)類型參數(shù)的未綁定泛型類進(jìn)行操作,請?jiān)?#34;<>"中使用","


Type類中添加了新的方法和屬性,用于提供有關(guān)該類型的泛型方面的反射信息,見MSDN。


.net泛型約束 ?
  如果客戶端代碼嘗試使用某個(gè)約束所不允許的類型來實(shí)例化類,則會產(chǎn)生編譯時(shí)錯(cuò)誤。這些限制稱為約束。約束是使用 where 上下文關(guān)鍵字指定的。
一、 約束
  下表列出了五種類型的約束:
約束 說明
T:struct
類型參數(shù)必須是值類型。可以指定除 Nullable 以外的任何值類型。
T:class
類型參數(shù)必須是引用類型,包括任何類、接口、委托或數(shù)組類型。
T:new()
類型參數(shù)必須具有無參數(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ù)約束和派生約束組合起來,前提是構(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 { }
引用約束
常見的
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í),必須在子類級別重復(fù)在基類級別規(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)用
復(fù)制代碼
public class MyClass5
{
? ? public void MyMethod<T>(T t){ }
}
public class App5
{
? ? public void CallMethod()
? ? {
? ? ? ? MyClass5 myclass5 = new MyClass5();
? ? ? ? myclass5.MyMethod<int>(3);
? ? }
}
復(fù)制代碼
3.泛型方法的重載
復(fù)制代碼
//第一組重載
?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;
? ? }
}
復(fù)制代碼
?
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
? ? ? ? { }
? ? }
四、虛擬方法
復(fù)制代碼
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)換
編譯器只允許將泛型參數(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;
? ? }
}
復(fù)制代碼?
?
變通方法:使用臨時(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)換
編譯器允許您將泛型參數(shù)顯式強(qiáng)制轉(zhuǎn)換到其它任何接口,但不能將其轉(zhuǎn)換到類


class MyClass1<T>
{
? ? void SomeMethod(T t)
? ? {
? ? ? ? ISomeInterface obj1 = (ISomeInterface)t; ?
? ? ? ? //BaseClass obj2 = (BaseClass)t; ? ? ? ? ? //不能通過編譯
? ? }
}


七、 泛型參數(shù)強(qiáng)制轉(zhuǎn)換到其他任何類型
使用臨時(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) { }
? ? }
}
========

泛型介紹(C# 編程指南)

https://msdn.microsoft.com/zh-cn/library/0x6a29h6.aspx


泛型類和泛型方法同時(shí)具備可重用性、類型安全和效率,這是非泛型類和非泛型方法無法具備的。 泛型通常用與集合以及作用于集合的方法一起使用。 .NET Framework 2.0 版類庫提供一個(gè)新的命名空間 System.Collections.Generic,其中包含幾個(gè)新的基于泛型的集合類。 建議面向 .NET Framework 2.0 及更高版本的所有應(yīng)用程序都使用新的泛型集合類,而不要使用舊的非泛型集合類如 ArrayList。 有關(guān)更多信息,請參見 .NET Framework 類庫中的泛型。
當(dāng)然,也可以創(chuàng)建自定義泛型類型和方法,以提供自己的通用解決方案,設(shè)計(jì)類型安全的高效模式。 下面的代碼示例演示一個(gè)用于演示用途的簡單泛型鏈接列表類。 (大多數(shù)情況下,應(yīng)使用 .NET Framework 類庫提供的 List<T> 類,而不是自行創(chuàng)建類。)在通常使用具體類型來指示列表中存儲的項(xiàng)的類型的場合,可使用類型參數(shù) T。 其使用方法如下:
在 AddHead 方法中作為方法參數(shù)的類型。
在 Node 嵌套類中作為公共方法 GetNext 和 Data 屬性的返回類型。
在嵌套類中作為私有成員數(shù)據(jù)的類型。
注意,T 可用于 Node 嵌套類。 如果使用具體類型實(shí)例化 GenericList<T>(例如,作為 GenericList<int>),則所有的 T 都將被替換為 int。
C#
? ? ? ? // type parameter T in angle brackets
? ? ? ? public class GenericList<T>?
? ? ? ? {
? ? ? ? ? ? // The nested class is also generic on T.
? ? ? ? ? ? private class Node
? ? ? ? ? ? {
? ? ? ? ? ? ? ? // T used in non-generic constructor.
? ? ? ? ? ? ? ? public Node(T t)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? next = null;
? ? ? ? ? ? ? ? ? ? data = t;
? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? private Node next;
? ? ? ? ? ? ? ? public Node Next
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? get { return next; }
? ? ? ? ? ? ? ? ? ? set { next = value; }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // T as private member data type.
? ? ? ? ? ? ? ? private T data;


? ? ? ? ? ? ? ? // T as return type of property.
? ? ? ? ? ? ? ? public T Data ?
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? get { return data; }
? ? ? ? ? ? ? ? ? ? set { data = value; }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? private Node head;
? ? ? ? ? ??
? ? ? ? ? ? // constructor
? ? ? ? ? ? public GenericList()?
? ? ? ? ? ? {
? ? ? ? ? ? ? ? head = null;
? ? ? ? ? ? }
? ? ? ? ? ? // T as method parameter type:
? ? ? ? ? ? public void AddHead(T t)?
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Node n = new Node(t);
? ? ? ? ? ? ? ? n.Next = head;
? ? ? ? ? ? ? ? head = n;
? ? ? ? ? ? }


? ? ? ? ? ? public IEnumerator<T> GetEnumerator()
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Node current = head;


? ? ? ? ? ? ? ? while (current != null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? yield return current.Data;
? ? ? ? ? ? ? ? ? ? current = current.Next;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
下面的代碼示例演示客戶端代碼如何使用泛型 GenericList<T> 類來創(chuàng)建整數(shù)列表。 只需更改類型參數(shù),即可方便地修改下面的代碼示例,創(chuàng)建字符串或任何其他自定義類型的列表:
C#
? ? ? ? class TestGenericList
? ? ? ? {
? ? ? ? ? ? static void Main()
? ? ? ? ? ? {
? ? ? ? ? ? ? ? // int is the type argument
? ? ? ? ? ? ? ? GenericList<int> list = new GenericList<int>();


? ? ? ? ? ? ? ? for (int x = 0; x < 10; x++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? list.AddHead(x);
? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? foreach (int i in list)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? System.Console.Write(i + " ");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? System.Console.WriteLine("\nDone");
? ? ? ? ? ? }
? ? ? ? }
請參閱
System.Collections.Generic
C# 編程指南
泛型
========

總結(jié)

以上是生活随笔為你收集整理的C# 泛型编程学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。