西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)編程開(kāi)發(fā)C#.NET → c#泛型使用詳解:泛型特點(diǎn)、泛型繼承、泛型接口、泛型委托

c#泛型使用詳解:泛型特點(diǎn)、泛型繼承、泛型接口、泛型委托

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:西西整理時(shí)間:2012/11/30 10:59:47字體大。A-A+

作者:西西點(diǎn)擊:1702次評(píng)論:1次標(biāo)簽: 泛型

  • 類型:安卓其它大小:4.4M語(yǔ)言:中文 評(píng)分:10.0
  • 標(biāo)簽:
立即下載

泛型:通過(guò)參數(shù)化類型來(lái)實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型。利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)靈活的復(fù)用。在.NET類庫(kù)中處處都可以看到泛型的身影,尤其是數(shù)組和集合中,泛型的存在也大大提高了程序員的開(kāi)發(fā)效率。更重要的是,C#的泛型比C++的模板使用更加安全,并且通過(guò)避免裝箱和拆箱操作來(lái)達(dá)到性能提升的目的。因此,我們很有必要掌握并善用這個(gè)強(qiáng)大的語(yǔ)言特性。

C#泛型特點(diǎn):

1、如果實(shí)例化泛型類型的參數(shù)相同,那么JIT編輯器會(huì)重復(fù)使用該類型,因此C#的動(dòng)態(tài)泛型能力避免了C++靜態(tài)模板可能導(dǎo)致的代碼膨脹的問(wèn)題。

2、C#泛型類型攜帶有豐富的元數(shù)據(jù),因此C#的泛型類型可以應(yīng)用于強(qiáng)大的反射技術(shù)。

3、C#的泛型采用“基類、接口、構(gòu)造器,值類型/引用類型”的約束方式來(lái)實(shí)現(xiàn)對(duì)類型參數(shù)的“顯示約束”,提高了類型安全的同時(shí),也喪失了C++模板基于“簽名”的隱式約束所具有的高靈活性

C#泛型繼承:

C#除了可以單獨(dú)聲明泛型類型(包括類與結(jié)構(gòu))外,也可以在基類中包含泛型類型的聲明。但基類如果是泛型類,它的類型要么以實(shí)例化,要么來(lái)源于子類(同樣是泛型類型)聲明的類型參數(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,也就是上面說(shuō)的來(lái)源于子類

F類型繼承于C<string,int>,個(gè)人認(rèn)為可以看成F繼承一個(gè)非泛型的類

G類型為非法的,因?yàn)镚類型不是泛型,C是泛型,G無(wú)法給C提供泛型的實(shí)例化

泛型類型的成員:

泛型類型的成員可以使用泛型類型聲明中的類型參數(shù)。但類型參數(shù)如果沒(méi)有任何約束,則只能在該類型上使用從System.Object繼承的公有成員。如下圖:

泛型接口:

泛型接口的類型參數(shù)要么已實(shí)例化,要么來(lái)源于實(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器無(wú)法確定泛型類型T和U是否不同,也就無(wú)法確定這兩個(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器無(wú)法確定約束條件中的A和B是否不同,也就無(wú)法確定這兩個(gè)方法是否不同

泛型方法重寫(xiě):

在重寫(xiě)的過(guò)程中,抽象類中的抽象方法的約束是被默認(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{}

}

對(duì)于MyClass中兩個(gè)重寫(xiě)的方法來(lái)說(shuō)

F方法是合法的,約束被默認(rèn)繼承

G方法是非法的,指定任何約束都是多余的

泛型約束:

1、C#泛型要求對(duì)“所有泛型類型或泛型方法的類型參數(shù)”的任何假定,都要基于“顯式的約束”,以維護(hù)C#所要求的類型安全。

2、“顯式約束”由where子句表達(dá),可以指定“基類約束”,“接口約束”,“構(gòu)造器約束”,“值類型/引用類型約束”共四種約束。

3、“顯式約束”并非必須,如果沒(méi)有指定“顯式約束”,范型類型參數(shù)將只能訪問(wèn)System.Object類型中的公有方法。例如:在開(kāi)始的例子中,定義的那個(gè)obj成員變量。比如我們?cè)陂_(kāi)始的那個(gè)例子中加入一個(gè)Test1類,在它當(dāng)中定義兩個(gè)公共方法Func1、Func2,如下圖:

我們今天來(lái)討論下泛型的用法。首先說(shuō)下泛型的概念,用通俗的語(yǔ)言來(lái)講,泛型其實(shí)就是類的一個(gè)參數(shù),但是要求參數(shù)必須是一個(gè)類,而不能是一個(gè)對(duì)象。很多人可能對(duì)泛型中T的作用不太理解,其中T在泛型中扮演的角色就相當(dāng)于一個(gè)占位符,確切的說(shuō),是類型占位符。凡是出現(xiàn)T的地方都會(huì)替換成你所傳遞的類型。

那么下面我們就來(lái)寫(xiě)一個(gè)泛型的例子,讓大家體驗(yàn)一下泛型的威力。

首先咱們來(lái)看常用的List<T>泛型集合

01,List<T>集合,其中T可以是任何類型(int,string,數(shù)組類型,甚至是用戶自定義的類類型)

            List<string> intList = new List<string>();

            intList.Add("李曉玲");

            intList.Add("章子怡");

            foreach (string item in intList)

            {

                Console.WriteLine(item);

            }

也可以在聲明List<T>時(shí)使用類似于數(shù)組初始化器的集合初始化器。

例如:List<string>  nameList=new  List<string>(){“Jack”,”Rose”,”Harvard”};

(該特性在.net3.0以及更高版本中使用)

List<T>常用方法:

  1. 要向泛型中添加一個(gè)元素:使用Add()方法

                        添加多個(gè)元素:使用AddRange()方法

 2.在指定位置插入元素使用Insert()方法

3.訪問(wèn)元素可以通過(guò)索引,也可以使用foreach循環(huán)遍歷

4.刪除元素可以使用Remove()或者RemovAt()方法,使用Clear()方法可以刪除所有元素。

然后來(lái)看下鍵值對(duì)泛型集合Dictionary<key,value>

C#也為HashTable提供了泛型類型,即Dictionary<K,V>,通常稱為”字典”。

Dictionary<K,V>存儲(chǔ)數(shù)據(jù)的特點(diǎn):

1, 存儲(chǔ)數(shù)據(jù)的方式和哈希表類似,也是通過(guò)key/value保存元素。

2, 鍵必須是唯一的。不能為null,但是如果值為引用類型,該值可以為空。

主要屬性:count:獲取包含的鍵/值對(duì)數(shù)

                     Keys:鍵的集合

//02,Dictionary<K,V>集合

            Dictionary<string, string> dic = new Dictionary<string, string>();

            dic.Add("01", "李小龍");

            dic.Add("02","李連杰");

            //遍歷key

            foreach (string item in dic.Keys)

            {

                Console.WriteLine("key"+item+"  value"+dic[item]);

            }

            //一次性遍歷鍵和值

            foreach (KeyValuePair<string,string> item in dic)

            {

                Console.WriteLine("key"+item.Key+"   value"+item.Value);

            }

 這時(shí)候大家可能會(huì)有疑問(wèn),為什么要用泛型呢?

泛型有三個(gè)好處:

1,實(shí)現(xiàn)算法的重用。

在泛型出現(xiàn)之前,我們?yōu)榱吮WC性能安全而自定義強(qiáng)類型集合時(shí),就需要為每種類型創(chuàng)建幾乎相同自定義集合。這樣就會(huì)重復(fù)勞動(dòng)而且可維護(hù)性差。

   2,避免拆箱和裝箱。

   這點(diǎn)大家可以這樣理解,使用ArrayList和HashTable存取變量,會(huì)帶來(lái)頻繁的裝箱(將值類型轉(zhuǎn)換成引用類型)和拆箱(將引用類型轉(zhuǎn)換成值類型)操作,對(duì)性能有所影響。

3,類型安全(編譯時(shí)會(huì)自動(dòng)檢測(cè)參數(shù)類型)

泛型的特點(diǎn):

泛型將操作的數(shù)據(jù)類型定義為一個(gè)參數(shù),類型參數(shù)使得設(shè)計(jì)如下類和方法成為可能。這些類和方法將一個(gè)或多個(gè)類型的指定推遲到客戶端代碼聲明并實(shí)例化類或方法的時(shí)候。

使用where約束類型參數(shù)

可以使用where約束類型參數(shù):

   Where  T:struct 中T必須在其繼承鏈中有System.ValueType值類型。

Where T:class 中T必須是引用類型

Where T:new()中T必須有一個(gè)默認(rèn)的構(gòu)造函數(shù)。在有多個(gè)約束的類型上,此約束必須列在末尾。

Where  T:NameOfBaseClass中T必須派生于NameOfBaseClass指定的類。

當(dāng)然,泛型不僅能用在類上,也可單獨(dú)用在類的方法中,它可根據(jù)方法參數(shù)的類型自動(dòng)適應(yīng)各種參數(shù),這樣的方法就叫做泛型方法。

Public  class  Stack2

{

      Public  void  Push<T>(Stack<T> s,  params T[] p)

{

       Foreach(T  t  in  p)

       {

          s.Push(t);

}

}

}

原來(lái)的類Stack一次只能Push一個(gè)數(shù)據(jù),這個(gè)類Stack2擴(kuò)展了Stack的功能,可以一次把多個(gè)數(shù)據(jù)壓入Stack中,其中Push是一個(gè)泛型方法。這個(gè)方法的調(diào)用示例如下:

Stack<int>  stack=new  Stack<int>(100);

Stack2  mystack2=new  Stack2();

mystack2.Push(x,1,2,3);

string  str=string.Empty;

for(int i=0;i<3;i++)

{

    Str+=stack.Pop().ToString();

}

結(jié)果輸出str的值是64321

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(1)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)