.NET泛型解析(下)-創(chuàng)新互聯(lián)

上一篇對.NET中的泛型進行了詳細的介紹以及使用泛型的好處是什么,這篇將更加深入的去了解泛型的其他的知識點,重頭戲.

創(chuàng)新互聯(lián)從2013年成立,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目成都網(wǎng)站制作、成都網(wǎng)站建設網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元平陽做網(wǎng)站,已為上家服務,為平陽各地企業(yè)和個人服務,聯(lián)系電話:13518219792

【1】泛型方法

上一篇我們也說過了,泛型可以是類,結構,接口,在這些泛型類型中定義的方法都可以叫做泛型方法,都可以引用由泛型類型本身指定的一個類型參數(shù)例如:

public class GenericType<T>

{

   private T G_Value;

   public T Convert<T> { T res = (T)Convert.ChangeType(G_value,typeof(T)); return res; }

}

泛型方法的存在為我們提供了極大的靈活性。

泛型方法顧名思義,首先它是一個方法,只不過這個方法的返回值,參數(shù)可能是泛型的,

類型推斷

類型推斷就是根據(jù)泛型方法中定義的形參類型T,在我們調(diào)用的使用,那么所要傳的也應該是一致的。例如:

static void Test<T >(ref T t1,ref T t2)

{

    T temp = t1;

    t1 = t2;

    t2 = temp;

}

這是我們定義的一個泛型方法,第一個參數(shù)類型為 T,第二個也為 T,說明這兩個類型是一致的。那么我們在調(diào)用的時候應該這樣 :

 int i = 8, j = 0 ; 
 Test( ref i, ref j);

而如果我們兩個實參的類型不統(tǒng)一的話,那么就會引發(fā)編譯異常例如 :

.NET泛型解析(下)

開放類型和封閉類型

具有泛型類型參數(shù)的類型對象讓就還是一個類型, CLR內(nèi)部依舊和其他的對象類型一樣創(chuàng)建一個內(nèi)部類型對象, 那么這種具有泛型類型參數(shù)的類型稱之為開放類型,開發(fā)類型不能進行構造任何的實例.

當泛型類型參數(shù)是一個實參時,那么所有的類型實參傳遞的都是實際的數(shù)據(jù)類型了,這種類型稱之為 封閉類型,封閉類型是允許構造實例對象的

class DictionaryStringKey <T> : IEnumerable<T>
 {
       public IEnumerator<T> GetEnumerator()
       {
           throw new NotImplementedException();
       }

       System .Collections. IEnumerator System. Collections.IEnumerable .GetEnumerator()
       {
           throw new NotImplementedException();
       }
 }

在上述代碼中,有一個DictionaryStringKey的類,繼承了一個IEnumable<T>的泛型,那么根據(jù)我們的開放類型它在調(diào)用的時候是不只是具體的實參,并且不能被構造實例的.

static void Main( string[] args)
        {
            object o = null;
            Type t = typeof( DictionaryStringKey <>);
           o =   CreateInstance(t);
           Console .ReadLine();

        }

        private static object CreateInstance( Type t)
        {
            object o = null;
            try
            {
                o = Activator . CreateInstance(t);
                Console .WriteLine( @" 創(chuàng)建了 " + t + "的實例 " , t .ToString());
            }
            catch (Exception ex)
            {
                o = Activator . CreateInstance(t);
                Console .WriteLine( @" 創(chuàng)建 " + t + "的實例失敗 " , t .ToString());
            }
          
            return o;
        }

上述代碼中我嘗試著對開放類型進行實例化,結果報出異常 :

.NET泛型解析(下)當我們傳入實參之后,那么它就是一個封閉類型,這樣我們就可以進行構造實例了.

static void Main( string[] args)
        {
            object o = null;
            Type t = typeof( DictionaryStringKey <string > );
           o =   CreateInstance(t);
           Console .ReadLine();

        }

【2】泛型接口

泛型的主要作用就是定義泛型的引用類型和值類型,在CLR中,對于泛型接口的支持也是很重要的,因為這樣更有益與程序的擴展性, 另外一點如果沒有泛型接口我們每次使用非泛型接口時都會進行裝箱操作(例如:  IComparable),并且會失去編譯時的安全性(因為它是非泛型的,較之泛型的好處之一).

那么CLR提供了對于泛型接口的支持,對于引用類型和值類型可以通過制定實參的方式來實現(xiàn)泛型接口,同時也可以保持未指定狀態(tài)來實現(xiàn)一個泛型接口( 接受者也可以是泛型 , 可以在后期進行指定類型)

實例 1 : 聲明一個泛型接口

interface IPair <T>
{
    T First { get; set ; }
    T Second { get; set ; }     
}

IPair這個接口實現(xiàn)了一對相關的對象,兩個數(shù)據(jù)項具有相同的類型.

實現(xiàn)接口時,語法與非泛型類的語法是相同的,如果在實現(xiàn)泛型接口時,同時不指定實參,則默認為是一個泛型類.

實例 2 : 泛型接口的實現(xiàn)

class Pair <T> : IPiar< T>
    {
        public T First
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public T Second
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }

CLR泛型接口的支持對于集合類型來講尤其重要,同時泛型在集合類型中較為常用,如果沒有泛型那么我們所使用List的時候都要依賴與System.Collections,我們在每次訪問的時候都需要執(zhí)行一次轉換,如果使用泛型接口,就可以避免執(zhí)行轉型,因為參數(shù)化的接口能實現(xiàn)更強的編譯時綁定.

實例 3 : 在一個類中多次實現(xiàn)相同的接口

interface IContainer <T>
   {
       ICollection<T > Items { get ; set; }
   }

    public class Person : IContainer<A >,IContainer <B>
    {

        public ICollection <A> Items
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        ICollection<B > IContainer <B>. Items
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }

Items屬性使用一個顯式接口實現(xiàn)多次出現(xiàn),每一次,類型參數(shù)都有所不同,如果沒有泛型,這是做不到的,在非泛型的情況下,CLR只允許一個顯式的IContainer.Items屬性.

【4】泛型約束(主要約束,次要約束,構造器約束)

約束也可以理解為是一種規(guī)則,意思就是我們所編寫的所有泛型,你在調(diào)用的時候,應該給我傳輸那些類型的實參。

在上一篇中,我們也在一個DataTableToList中使用到了約束,但是并沒有進行講解,在這里我們詳細的說明一下:

在.NET 中有4中約束方式,它們的常規(guī)語法是相同的,約束要放在泛型方法或者泛型類型聲明的末尾,并由上下文關鍵字 ”where :“  來引入 。

主要約束(引用類型約束):

主要約束表示的是 : 我們在指定一個引用類型約束時,那么一個指定的類型實參要么是與約束類型相同的類型,要么是從約束類型派生的一個類型

實例 4 : 引用類型約束

struct Generic<T>(T t1) where : class

這里我定義了一個泛型方法,Generic,后來寫了一個where : class,這就告訴編譯器,在使用者調(diào)用這個方法時,必須為這個方法的傳入一個引用類型的實參,同時,我們也可以注意到這個方法的返回類型為struct值類型。

主要約束(值類型約束)

很明顯,值類型約束的話,就是將 約束條件指定為 Struct

實例 5 : 值類型約束

class ConstraintOfStruct <T> where T : struct
 {
     public T result()
     {
         return new T();
     }
 }

在代碼中,我們最后返回的是new T(),這個是沒有問題的,因為我們已經(jīng)可以肯定T就是值類型,所有的值類型都有一個隱式的構造函數(shù),那么如果我們將 約束條件改為 class的話,那么就會出異常,因為不是所有的引用類型都可以實例化.

實例 6 : 反面教材 - 約束為引用類型時進行實例化.

.NET泛型解析(下)

構造函數(shù)類型約束

構造函數(shù)類型約束表示為 T : new(),這個約束必須為所有的類型參數(shù)的最后一個約束,它用于檢查類型實參是否有一個可用于創(chuàng)建類型實例的無參構造函數(shù),這一點比較適用于所有的值類型,所有的沒有顯式聲明構造函數(shù)的非靜態(tài)、非抽象類,所有顯式聲明了一個公共無參構造函數(shù)的非抽象類。

實例 7 : 構造函數(shù)類型約束

public T CreateInatance<T >() where T : new()
{
     return new T();
}

在方法createInstance中,要求我們必須傳入一個無參的構造函數(shù),例如:我們可以傳入 object,struct,stream等,但是不能傳入 string,Directory等.

接口約束:

接口約束的一個好處就是我們可以指定多個接口,但是只能指定一個類

class ConstraintOfStruct <T> where T : class,IEquatable <T> ,IComparable<T>{}

組合約束 :

組合約束就是指定多個約束條件在上一個約束中我們已經(jīng)看到了 ,更詳細的如下 :

class Sample<T> where T : class ,IDisposable,new(){}
class Sample<T> where T : struct,IDisposable{}     
class Sample<T,U> where T : Stream where U : IDisposable{}
class Sample<T> where T : class ,struct

【5】泛型類型轉型  

public static T Desercialies <T > (Stream stream, IFormatter formatter)
{       
   return (T)formatter. Deserialize(stream);
}

formatter 負責將流轉換為 Object,返回一個Object類型,我們在使用泛型調(diào)用的時候應該這樣來 :

string result = Desercialies <string > (stream, formatter);

上述的代碼看著是一種強制轉換,但是仍然執(zhí)行了隱式的轉換,就和使用非泛型 string result = (string)Desercialies(stream, formatter); 一樣

【6】泛型和屬性

 屬性也可以應用到泛型類型中,使用的方式和非泛型類型相同.自定義的屬性只允許引用開發(fā)泛型類型

class MyClass<T,S> where T :class

     where S : struct

  {

    public T MyName { get; set; }

    public S MyCode { get; set; }

    public List<T> MyCourse { get; set; }

    public List<S> MyStudyHistory { get; set; }

  }

上述我們定義了一個MyClass 類,這個類有兩個參數(shù)一個是引用類型一個是值類型.在屬性MyName,MyCourse的類型都是引用類型,MyCode的類型都為值類型

泛型類型構造器:

class Pair < T> : IPiar< T >

  {

    private T _first;

    public T First

    {

      get { return _first; }

      set { _first = value; }

    }

    private T _second;

    public T Second

    {

      get { return _second; }

      set { _second = value; }

    }

    public Pair(T first,T second)

    {

    }

  }

  interface IPiar < T> { }

型的構造器不需要添加類型參數(shù)來與類的聲明一致.

先到這里, 下一篇著重分享協(xié)變和逆變,否則這一篇符太長,不利于以后的查看.

泛型委托和泛型反射留在深入總結委托和反射的時候進行總結。

如果你覺得本文對你有幫助的話,請點右下角的推薦,或者直接關注我,后續(xù)將不斷更新.NET解析這一系列的文章....

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

本文題目:.NET泛型解析(下)-創(chuàng)新互聯(lián)
當前網(wǎng)址:http://bm7419.com/article30/hssso.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站網(wǎng)站改版、全網(wǎng)營銷推廣、ChatGPT、微信小程序、網(wǎng)站建設

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化