【Clr in c#】泛型

來源:互聯網
上載者:User

標籤:des   style   blog   io   color   ar   os   使用   sp   

  使用泛型的好處是“代碼重用”,極大的提高了開發效率,泛型為開發人員提供了以下優勢:

    1,原始碼保護  演算法的原始碼不需要提供給使用泛型演算法的開發人員,使用c++模板的泛型技術需要提供。(目前c++模板的泛型技術瞭解較少)

    2,型別安全    給泛型演算法指定類型時,編譯器能理解開發人員意圖,只有相容類型能通過,不相容的時候編譯時間候會報錯。

    3,更清晰的代碼  由於編譯器強制類型的安全性,減少原始碼中必須進行的轉型次數,使得代碼容易維護和編寫。例如:DateTime dt=dtList[0];從DateTime的集合中按照索引取出來的值可以直接賦值給DateTime類型,不需要轉型。

    4,更佳的效能 在操作實值型別時候,非泛型集合會造成裝箱、拆箱操作,會造成託管堆上的記憶體配置,會造成頻繁的記憶體回收,影響效能。

 

1.泛型基礎結構  1.1 開放類型和封閉類型

      具有泛型型別參數的類型稱為開放類型。

        不能建立執行個體。例如Dictionary<,>,沒有指定參數,目前尚不清楚這個開放類型有什麼用。

      所有類型實參傳遞的都是實際資料類型為封閉類型。

        使用約束無法將類型實參限制為某一類型,可以用一個靜態構造器來保證類型。如下

      

internal sealed class GenericTypeThatRequiresAnEnum<T>{  static   GenericTypeThatRequiresAnEnum(){    if(!typeof(T).IsEnum){      throw new ArgumentException("T must be an enumerated type");    }  }}
  1.2泛型型別的繼承

    泛型型別仍然是類型,它能從其他任何類型派生。

    public class Node1<T>    {        public T m_data;        public Node1<T> m_next;        public Node1(T data) : this(data, null) { }        public Node1(T data, Node1<T> next)        {            m_data = data;            m_next = next;        }        public override string ToString()        {            // ABC            return m_data.ToString()+((m_next!=null)?m_next.ToString():null);        }    }

  上面例子必須是相同資料類型下使用,加入鏈表需要多個m_data為多種類型的時候這種結構將無法滿足,這時候我們可以考慮抽出一個非泛型的基類,這樣繼承的泛型就可以指定多種類型。這是一個泛型應用的技巧。

public class Node2    {        protected Node2 m_next;        public Node2(Node2 next)        {            m_next = next;        }    }   public class TypeNode<T> : Node2 {        public T m_data;        public TypeNode(T data,Node2 next):base(next){            m_data = data;        }        public TypeNode(T data):this(data,null){        }        public override string ToString()        {            // Tody is 時間。            return m_data.ToString() + ((m_next != null) ? m_next.ToString() : null);        }    }
1.3泛型型別的同一性

  這種性質不經常用,這裡簡單記一下只當瞭解。

  簡化泛型的寫法多封裝一層去除"<"">"。

  class DateTimeList:List<DateTime>{

  //這裡不需要放入任何代碼。

}

這樣使用的時候就沒有<,>符號了。

DateTimeList dt=new DateTimeList();

這隻是表面方便了,絕對不要單純出於增強代碼可讀性目的定義一個新類,事實上也不會這麼做,但是這樣寫會喪失同一性和相等性,如下代碼為Flase

Boolean sameType=(typeof(List<DateTime>)==typeof(DateTimeList));

可以通過使用using指令彌補相等性,添加如下結果為True;

using DateTimeList=System.Collections.Generic.List<System.DateTime>;

 

1.4代碼爆炸

  使用泛型型別參數的一個方法在JIT(即時編譯)編譯時間,Clr擷取方法的IL,用指定的實參進行替換,建立恰當的本地代碼,缺點是CLR要為每種不同的方法、類型組合產生本地代碼,可能造成應用程式集顯著增大,損壞效能,稱之為 代碼爆炸。

  但是CRL內建了一些最佳化措施,緩解代碼爆炸。所有程式集使用List<DateTime>時候,只會產生一次,認為所有參考型別實參都是完全相同,List<String>和List<Stream>可以公用,之所以會這樣,是因為所有參考型別的實參或者變數實際都是指向堆上的對象指標,而指標全部都是以相同的方式來操作。

2,泛型介面

  泛型介面的一個例子是IComparable介面,在介面裡詳細寫

3,泛型委派

  建議使用泛型的Action和Func委託,會在以後的委託中細說

4,委託和介面的逆變和協變泛型型別實參

  不變數(invariant)表示泛型型別不可變。

  逆變數(contravariant)表示泛型型別參數可以從一個基類更改為該類的衍生類別,用in關鍵字標記,只出現在輸入位置。

  協變數(covariant) 表示泛型型別可以從一個衍生類別更改為它的基底類型,用out關鍵字標記,只出現在輸出位置。

  public delegate TResult Func<in T,out TResult>(T arg);

  Func<object,ArgumentException> fn1=null;

  func<string,Exception> fn2=fn1;//這裡不需要顯示轉換,因為逆變數,協變數

  調用委託Exception e=fn2("");

  

  使用要擷取泛型參數和傳回值的委託時,建議盡量使用in和out關鍵字,因為不會有不良反應。

  泛型介面和泛型委派一樣也可以用out和in。

5,泛型方法

   用一個例子介紹下泛型的定義,下面一個類型定義了一個型別參數,一個方法定義了它自己的專用型別參數。

  

class GenericType<T>{  private T m_value;  public GenericType(T value){m_value=value;}  public TOutput Coverter(TOutput)(){        TOutput  result=(TOutput)Convert.ChangeType(m_value,typeof(TOutput ));      return   result;  }  }

  下面寫一個比較經典常用的泛型方法,2個參數互換

private static void Swap<T>(ref T o1,ref T o2){  T temp=o1;  o1=o2;  o2=temp;    }

 

6泛型約束

  確保使用當前泛型是自己想要的類型。

 例如如下方法,在類型沒有提供CompareTo方法時候會報錯。

 private static T Min<T>(T o1,To2){

    if(o1.CompareTo(o2)<0)

      return o1;

    return o2;

  }

   這個時候我們就需要在該泛型方法添加泛型約束。

 private static T Min<T>(T o1,To2) where T:IComparable<T>{

    if(o1.CompareTo(o2)<0)

      return o1;

    return o2;

  }

泛型約束主要分為3種。

1,主要約束   主要約束可以是一個參考型別,實參必須與約束相同或者派生,

例如where T:Stream ,使用該泛型方法必須是Stream 類型或者其衍生類別型。

where T:Class,使用該泛型方法必須是參考型別。

2,次要約束   次要約束代表的是一個借口類型,指定的參數必須實現所有介面約束例如 where T:IComparable<T>

3,構造器約束    指定的實參必須實現公用無參構造器的一個非抽象類別型where T:New()

 

  

 下面是項目中用到的一個泛型方法,模板還原序列化。使用了Newtonsoft.Json

        public T GetTemplateData<T>() where T : TemplateData        {            if (!string.IsNullOrEmpty(TemplateDataJsonStr))            {                T obj = (T)JsonConvert.DeserializeObject(TemplateDataJsonStr, typeof(T));                obj.CheckField();                return obj;            }            else return null;                    }        public void SetTemplateData(TemplateData templateData)         {           TemplateDataJsonStr= JsonConvert.SerializeObject(templateData);        }

 

 

 

  

【Clr in c#】泛型

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.