亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#的泛型方法解析

2019-10-29 21:17:52
字體:
來源:轉載
供稿:網友

C#2.0引入了泛型這個特性,由于泛型的引入,在一定程度上極大的增強了C#的生命力,可以完成C#1.0時需要編寫復雜代碼才可以完成的一些功能。但是作為開發者,對于泛型可謂是又愛又恨,愛的是其強大的功能,以及該特性帶來的效率的提升,恨的是泛型在復雜的時候,會呈現相當復雜的語法結構。這種復雜不僅是對于初學者,對于一些有開發經驗的.NET開發者,也是一個不那么容易掌握的特性。

   接下來我們來了解一下C#2.0加入的特性:泛型。

一.泛型的基本特性概述:

    在實際項目開發中,任何API只要將object作為參數類型和返回類型使用,就可能在某個時候涉及強類型轉換。提到強類型轉換,估計很多開發者第一反應就是“效率”這個次,對于強類型的利弊主要看使用者使用的環境,天底下沒有絕對的壞事,也沒有絕對的好事,有關強類型的問題不是本次的重點,不做重點介紹。

    泛型是CLR和C#提供的一種特殊機制,支持另一種形式的代碼重用,即“算法重用”。泛型實現了類型和方法的參數化,泛型類型和方法也可以讓參數告訴使用者使用什么類型。

    泛型所帶來的好處:更好的編譯時檢查,更多在代碼中能直接表現的信息,更多的IDE支持,更好的性能??赡苡腥藭蓡枺瑸槭裁捶盒蜁磉@么多好處,使用一個不能區分不同類型的常規API,相當于在一個動態環境中訪問那個API。

    CLR允許創建泛型引用和泛型值類型,但是不允許創建泛型枚舉,并且CLR允許創建泛型接口和泛型委托,CLR允許在引用類型、值類型或接口中定義泛型方法。定義泛型類型或方法時,為類型指定了任何變量(如:T)都稱為類型參數。(T是一個變量名,在源代碼中能夠使用一個數據類型的任何位置,都可以使用T)在C#中泛型參數變量要么成為T,要么至少一大寫T開頭。

二.泛型類、泛型接口和泛型委托概述:

   1.泛型類:

    泛型類型仍然是類型,所以可以從任何類型派生。使用一個泛型類型并指定類型實參時,實際是在CLR中定義一個新類型對象,新類型對象是從泛型派生自的那個類型派生的。使用泛型類型參數的一個方法在基尼險那個JIT編譯時,CLR獲取IL,用指定的類型實參進行替換,然后創建恰當的本地代碼。

    如果沒有為泛型類型參數提供類型實參,那就么就是未綁定泛型類型。如果指定了類型實參,該類型就是已構造類型。已構造類型可以是開發或封閉的,開發類型還包含一個類ixngcanshu,而封閉類型則不是開發的,類型的每個部分都是明確的。所有代碼實際都是在一個封閉的已構造類型的上下文中執行。

   泛型類在.NET的應用主要在集合類中,大多數集合類在System.Collections.Generic和System.Collections.ObjectModel類中。下面簡單的介紹一種泛型集合類:

     (1).SynchronizedCollection:提供一個線程安全集合,其中包含泛型參數所指定類型的對象作為元素.

  [ComVisible(false)] public class SynchronizedCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable { /// <summary> /// 初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新實例。 /// </summary> public SynchronizedCollection(); /// <summary> /// 通過用于對線程安全集合的訪問進行同步的對象來初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新實例。 /// </summary> /// <param name="syncRoot">用于對線程安全集合的訪問進行同步的對象。</param><exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 為 null。</exception> public SynchronizedCollection(object syncRoot); /// <summary> /// 使用指定的可枚舉元素列表和用于對線程安全集合的訪問進行同步的對象來初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新實例。 /// </summary> /// <param name="syncRoot">用于對線程安全集合的訪問進行同步的對象。</param><param name="list">用于初始化線程安全集合的元素的 <see cref="T:System.Collections.Generic.IEnumerable`1"/> 集合。</param><exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 或 <paramref name="list"/> 為 null。</exception> public SynchronizedCollection(object syncRoot, IEnumerable<T> list); /// <summary> /// 使用指定的元素數組和用于對線程安全集合的訪問進行同步的對象來初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新實例。 /// </summary> /// <param name="syncRoot">用于對線程安全集合的訪問進行同步的對象。</param><param name="list">用于初始化線程安全集合的 <paramref name="T"/> 類型元素的 <see cref="T:System.Array"/>。</param><exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 或 <paramref name="list"/> 為 null。</exception> public SynchronizedCollection(object syncRoot, params T[] list); /// <summary> /// 將項添加到線程安全只讀集合中。 /// </summary> /// <param name="item">要添加到集合的元素。</param><exception cref="T:System.ArgumentException">設置的值為 null,或者不是集合的正確泛型類型 <paramref name="T"/>。</exception> public void Add(T item); /// <summary> /// 從集合中移除所有項。 /// </summary> public void Clear(); /// <summary> /// 從特定索引處開始,將集合中的元素復制到指定的數組。 /// </summary> /// <param name="array">從集合中復制的 <paramref name="T "/>類型元素的目標 <see cref="T:System.Array"/>。</param><param name="index">復制開始時所在的數組中的從零開始的索引。</param> public void CopyTo(T[] array, int index); /// <summary> /// 確定集合是否包含具有特定值的元素。 /// </summary> ///  /// <returns> /// 如果在集合中找到元素值,則為 true;否則為 false。 /// </returns> /// <param name="item">要在集合中定位的對象。</param><exception cref="T:System.ArgumentException">設置的值為 null,或者不是集合的正確泛型類型 <paramref name="T"/>。</exception> public bool Contains(T item); /// <summary> /// 返回一個循環訪問同步集合的枚舉數。 /// </summary> ///  /// <returns> /// 一個 <see cref="T:System.Collections.Generic.IEnumerator`1"/>,用于訪問集合中存儲的類型的對象。 /// </returns> public IEnumerator<T> GetEnumerator(); /// <summary> /// 返回某個值在集合中的第一個匹配項的索引。 /// </summary> ///  /// <returns> /// 該值在集合中的第一個匹配項的從零開始的索引。 /// </returns> /// <param name="item">從集合中移除所有項。</param><exception cref="T:System.ArgumentException">設置的值為 null,或者不是集合的正確泛型類型 <paramref name="T"/>。</exception> public int IndexOf(T item); /// <summary> /// 將一項插入集合中的指定索引處。 /// </summary> /// <param name="index">要從集合中檢索的元素的從零開始的索引。</param><param name="item">要作為元素插入到集合中的對象。</param><exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的項數。</exception><exception cref="T:System.ArgumentException">設置的值為 null,或者不是集合的正確泛型類型 <paramref name="T"/>。</exception> public void Insert(int index, T item); /// <summary> /// 從集合中移除指定項的第一個匹配項。 /// </summary> ///  /// <returns> /// 如果從集合中成功移除了項,則為 true;否則為 false。 /// </returns> /// <param name="item">要從集合中移除的對象。</param> public bool Remove(T item); /// <summary> /// 從集合中移除指定索引處的項。 /// </summary> /// <param name="index">要從集合中檢索的元素的從零開始的索引。</param><exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的項數。</exception> public void RemoveAt(int index); /// <summary> /// 從集合中移除所有項。 /// </summary> protected virtual void ClearItems(); /// <summary> /// 將一項插入集合中的指定索引處。 /// </summary> /// <param name="index">集合中從零開始的索引,在此處插入對象。</param><param name="item">要插入到集合中的對象。</param><exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的項數。</exception><exception cref="T:System.ArgumentException">設置的值為 null,或者不是集合的正確泛型類型 <paramref name="T"/>。</exception> protected virtual void InsertItem(int index, T item); /// <summary> /// 從集合中移除指定 <paramref name="index"/> 處的項。 /// </summary> /// <param name="index">要從集合中檢索的元素的從零開始的索引。</param><exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的項數。</exception> protected virtual void RemoveItem(int index); /// <summary> /// 使用另一項替換指定索引處的項。 /// </summary> /// <param name="index">要替換的對象的從零開始的索引。</param><param name="item">要替換的對象。</param><exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的項數。</exception> protected virtual void SetItem(int index, T item); /// <summary> /// 返回一個循環訪問同步集合的枚舉數。 /// </summary> ///  /// <returns> /// 一個 <see cref="T:System.Collections.Generic.IEnumerator`1"/>,用于訪問集合中存儲的類型的對象。 /// </returns> IEnumerator IEnumerable.GetEnumerator(); /// <summary> /// 從特定索引處開始,將集合中的元素復制到指定的數組。 /// </summary> /// <param name="array">從集合中復制的 <paramref name="T"/> 類型元素的目標 <see cref="T:System.Array"/>。</param><param name="index">復制開始時所在的數組中的從零開始的索引。</param> void ICollection.CopyTo(Array array, int index); /// <summary> /// 向集合中添加一個元素。 /// </summary> ///  /// <returns> /// 新元素的插入位置。 /// </returns> /// <param name="value">要添加到集合中的對象。</param> int IList.Add(object value); /// <summary> /// 確定集合是否包含具有特定值的元素。 /// </summary> ///  /// <returns> /// 如果在集合中找到元素 <paramref name="value"/>,則為 true;否則為 false。 /// </returns> /// <param name="value">要在集合中定位的對象。</param><exception cref="T:System.ArgumentException"><paramref name="value"/> 不是集合所含類型的對象。</exception> bool IList.Contains(object value); /// <summary> /// 確定集合中某個元素的從零開始的索引。 /// </summary> ///  /// <returns> /// 如果在集合中找到,則為 <paramref name="value"/> 的索引;否則為 -1。 /// </returns> /// <param name="value">集合中要確定其索引的元素。</param> int IList.IndexOf(object value); /// <summary> /// 將某個對象插入到集合中的指定索引處。 /// </summary> /// <param name="index">從零開始的索引,將在該位置插入 <paramref name="value"/>。</param><param name="value">要在集合中插入的對象。</param><exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小于零或大于集合中的項數。</exception><exception cref="T:System.ArgumentException">設置的 <paramref name="value"/> 為 null,或者不是集合的正確泛型類型 <paramref name="T"/>。</exception> void IList.Insert(int index, object value); /// <summary> /// 從集合中移除作為元素的指定對象的第一個匹配項。 /// </summary> /// <param name="value">要從集合中移除的對象。</param> void IList.Remove(object value); }

     (2).KeyedByTypeCollection:提供一個集合,該集合的項是用作鍵的類型。

  [__DynamicallyInvokable] public class KeyedByTypeCollection<TItem> : KeyedCollection<Type, TItem> { /// <summary> /// 初始化 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 類的新實例。 /// </summary> public KeyedByTypeCollection(); /// <summary> /// 根據指定的對象枚舉初始化 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 類的新實例。 /// </summary> /// <param name="items">泛型類型 <see cref="T:System.Object"/> 的 <see cref="T:System.Collections.Generic.IEnumerable`1"/>,用于初始化集合。</param><exception cref="T:System.ArgumentNullException"><paramref name="items"/> 為 null。</exception> public KeyedByTypeCollection(IEnumerable<TItem> items); /// <summary> /// 返回集合中第一個具有指定類型的項。 /// </summary> ///  /// <returns> /// 如果為引用類型,則返回類型 <paramref name="T"/> 的對象;如果為值類型,則返回類型 <paramref name="T"/> 的值。 如果集合中不包含類型 <paramref name="T"/> 的對象,則返回類型的默認值:如果是引用類型,默認值為 null;如果是值類型,默認值為 0。 /// </returns> /// <typeparam name="T">要在集合中查找的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public T Find<T>(); /// <summary> /// 從集合中移除具有指定類型的對象。 /// </summary> ///  /// <returns> /// 從集合中移除的對象。 /// </returns> /// <typeparam name="T">要從集合中移除的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public T Remove<T>(); /// <summary> /// 返回 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 中包含的類型 <paramref name="T"/> 的對象的集合。 /// </summary> ///  /// <returns> /// 一個類型 <paramref name="T"/> 的 <see cref="T:System.Collections.ObjectModel.Collection`1"/>,包含來自原始集合的類型 <paramref name="T"/> 的對象。 /// </returns> /// <typeparam name="T">要在集合中查找的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public Collection<T> FindAll<T>(); /// <summary> /// 從集合中移除所有具有指定類型的元素。 /// </summary> ///  /// <returns> /// <see cref="T:System.Collections.ObjectModel.Collection`1"/>,包含來自原始集合的類型 <paramref name="T"/> 的對象。 /// </returns> /// <typeparam name="T">要從集合中移除的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public Collection<T> RemoveAll<T>(); /// <summary> /// 獲取集合中包含的某個項的類型。 /// </summary> ///  /// <returns> /// 集合中指定的 <paramref name="item"/> 的類型。 /// </returns> /// <param name="item">集合中要檢索其類型的項。</param><exception cref="T:System.ArgumentNullException"><paramref name="item"/> 為 null。</exception> [__DynamicallyInvokable] protected override Type GetKeyForItem(TItem item); /// <summary> /// 在集合中的特定位置插入一個元素。 /// </summary> /// <param name="index">從零開始的索引,應在該位置插入 <paramref name="item"/>。</param><param name="item">要在集合中插入的對象。</param><exception cref="T:System.ArgumentNullException"><paramref name="item"/> 為 null。</exception> [__DynamicallyInvokable] protected override void InsertItem(int index, TItem item); /// <summary> /// 使用一個新對象替換指定索引處的項。 /// </summary> /// <param name="index">要替換的 <paramref name="item"/> 的從零開始的索引。</param><param name="item">要添加到集合中的對象。</param><exception cref="T:System.ArgumentNullException"><paramref name="item"/> 為 null。</exception> [__DynamicallyInvokable] protected override void SetItem(int index, TItem item); }

   2.泛型接口和泛型委托:

     泛型的主要作用就是定義泛型的引用類型和指類型。一個引用類型或值類型可通過指定類型實參的方式實現泛型接口,也可以保持類型實參的未指定狀態實現一個泛型接口。

     具體看一下泛型接口IEnumerable:公開枚舉數,該枚舉數支持在非泛型集合上進行簡單迭代。

  [ComVisible(true)] [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")] [__DynamicallyInvokable] public interface IEnumerable { /// <summary> /// 返回一個循環訪問集合的枚舉數。 /// </summary> ///  /// <returns> /// 一個可用于循環訪問集合的 <see cref="T:System.Collections.IEnumerator"/> 對象。 /// </returns> /// <filterpriority>2</filterpriority> [DispId(-4)] [__DynamicallyInvokable] IEnumerator GetEnumerator(); }

  CLR支持泛型委托,目的是保證任何類型的對象都能以一種類型安全的方式傳給一個回調方法。泛型委托允許一個孩子類型實例在傳給一個回調方法時不執行任何裝箱處理。委托時機只提供了4個方法:一個構造器,一個Invlke方法,一個BeginInvoke方法和一個EndInvoke方法。如果定義的一個委托類型指定了類型參數,編譯器會定義委托類的方法,用指定的類型參數替換方法的參數類型和值類型。

  以上是對泛型類、泛型接口和泛型委托的簡單了解,本文的目的主要是講解泛型方法,下面我們具體了解一些泛型泛型的知識。

三.泛型方法解析:

 1.泛型方法概述: 

    定義泛型類、結構或接口時,類型中定義的任何方法都可引用類型指定的一個類型參數。類型參數可以作為方法的參數,作為方法的返回值,或者作為方法內部定義的一個局部變量來使用。CLR允許一個方法指定它獨有的類型參數,這些類型參數可用于參數、返回值、或者局部變量。

   C#編譯器支持在調用一個泛型方法時進行類型推斷。執行類型推斷時,C#使用變量的數據類型,而不是由變量引用的對象的實際類型。一個類型可以定義多個方法,讓其中一個方法接受具體的數據類型,讓另一個方法接受泛型類型參數。

    泛型方法示例:

 List<TOutput> ConverAll<TOutput>(Conver<T,TOutput> conv)List<TOutput>:返回類型(一個泛型列表)。ConverAll:方法名。<TOutput>:類型參數。Conver<T,TOutput>:參數類型(泛型委托)。conv:參數名。

 對以上的示例代碼分析,需要掌握:為每個類型參數使用一個不同的類型,在整體應用這些類型參數。

  (1).首先替換包含方法(List<T>的T部分)的那個類型的類型參數,如將T替換為string:

List<TOutput> ConverAll<TOutput>(Conver<string,TOutput> conv)

  (2).處理完T后,再需要處理的就是TOutput,可以看出它是一個方法類型參數,這里采用guid替換TOutput。

List<Guid> ConverAll(Conver<string,Guid> conv)

  對TOutput賦予類型實參后,可以移除生命中的類型參數<TOutput>,將方法堪稱非泛型方法,如上。以上的示例可以處理一個字符串列表,用一個轉換器來生成一個Guid列表。

  將原始列表中的每個元素都轉換成目標類型,將轉換后的元素添加到一個列表中,最后返回這個列表。以上的處理方式,主要將其泛型方法的參數進行逐一的細化,無論在什么學科,都需要將復雜的問題進行簡單化,將抽象的問題具體化,這也是一種常用的處理方式。

 2.類型約束:

    約束的作用是限制能指定成泛型實參的類型數量。通過限制類型的數量,我們可以對那些類型執行更多的操作。約束可以應用于一個泛型類型的類型參數,也可以應用于一個泛型方法的類型參數。CLR不允許基于類型參數名稱或約束進行重載,只能基于元數對類型或方法進行重載。不允許為重寫方法的類型參數指定任何約束,但是類型實參的名稱是可以改變的。

    泛型約束的操作,約束要放到泛型方法或泛型類型聲明的末尾,并由上下文關鍵where引入。

   (1).引用類型約束:

      引用類型約束:用于確保使用的類型實參是引用類型。(表示為:T:class,且必須為類型參數指定的第一個約束。)

   (2).值類型約束:

      值類型約束:用于確保使用的類型參數是指類型。(表示為:T:struct,可空類型不包含在內)

   (3).構造函數類型約束:

       構造函授類型約束:指定所有類型參數的最后一個約束,它檢查類型實參是否有一個可用于創建實例的無參構造函數。(表示為:T:new())適用于所有值類型,所有沒有顯示聲明構造函數的非靜態、非抽象類,所有顯示聲明了一個公共無參構造函數的非抽象類。

   (4).轉換類型約束:

      轉換類型約束:允許你指定另一個類型,類型實參必須可以通過一致性、引用或裝箱轉換隱式地轉換為該類型。還可以規定類型實參必須可以轉換為另一個類型實參。(例:class Sample<T> where T:Stream)

   (5).組合約束:

      組合約束:所個約束組合在一起的約束,但是組合約束也有限制條件。因為沒有任何類型即是引用類型,又是值類型。由于每一個值都有一個無參構造函數,所以假如已經有一個值類型約束,就不允許再指定一個構造函數約束。如果存在多個類型約束,并且其中一個為類,那么它應該出現在接口的前面,而且我們不能多次指定同一個接口。不同的類型參數可以用不同的約束,分別由一個where引入。

   備注:類型推斷只適用于泛型方法,不適用于泛型類型。

  以上是對泛型方法的相關概念和約束做了簡單的解析,接下來看一下.NET中一些發行方法的具體實現:

 /// <summary> /// 封裝一個方法,該方法具有四個參數并且不返回值。 /// </summary> /// <param name="arg1">此委托封裝的方法的第一個參數。</param><param name="arg2">此委托封裝的方法的第二個參數。</param><param name="arg3">此委托封裝的方法的第三個參數。</param><param name="arg4">此委托封裝的方法的第四個參數。</param><typeparam name="T1">此委托封裝的方法的第一個參數類型。</typeparam><typeparam name="T2">此委托封裝的方法的第二個參數類型。</typeparam><typeparam name="T3">此委托封裝的方法的第三個參數類型。</typeparam><typeparam name="T4">此委托封裝的方法的第四個參數類型。</typeparam><filterpriority>2</filterpriority> [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] [__DynamicallyInvokable] public delegate void Action<in T1, in T2, in T3, in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
 /// <summary> /// 表示比較同一類型的兩個對象的方法。 /// </summary> ///  /// <returns> /// 一個有符號整數,指示 <paramref name="x"/> 與 <paramref name="y"/> 的相對值,如下表所示。 值 含義 小于 0 <paramref name="x"/> 小于 <paramref name="y"/>。 0 <paramref name="x"/> 等于 <paramref name="y"/>。 大于 0 <paramref name="x"/> 大于 <paramref name="y"/>。 /// </returns> /// <param name="x">要比較的第一個對象。</param><param name="y">要比較的第二個對象。</param><typeparam name="T">要比較的對象的類型。</typeparam><filterpriority>1</filterpriority> [__DynamicallyInvokable] public delegate int Comparison<in T>(T x, T y);

  四.泛型方法應用代碼示例:

   以上講解的有關泛型方法的內容,這里提供一個有關泛型方法操作XML的代碼:

 /// <summary> /// 泛型方法:編譯器能夠根據傳入的方法參數推斷類型參數;它無法僅從約束或返回值推斷類型參數 /// </summary> public class ObjectXmlSerializer {  /// <summary>  /// 文件的反序列化  /// </summary>  /// <typeparam name="T">返回值類型</typeparam>  /// <param name="fileName"></param>  /// <returns>  /// 如果日志啟用,則發生異常時,異常寫入日志,若日志沒有開啟,則直接拋出異常信息  /// loggingEnabled==true: Null is returned if any error occurs.  /// loggingEnabled==false: throw exception  /// </returns>  public static T LoadFromXml<T>(string fileName) where T : class  {   return LoadFromXml<T>(fileName, true);  }  /// <summary>  /// 文件反序列化,若發生異常,異常信息寫入日志  /// </summary>  /// <typeparam name="T">加載類的類型</typeparam>  /// <param name="fileName">文件名字</param>  /// <param name="loggingEnabled">啟用日志記錄</param>  /// <returns></returns>  public static T LoadFromXml<T>(string fileName, bool loggingEnabled) where T : class  {   FileStream fs = null;   try   {    var serializer = new XmlSerializer(typeof(T));    fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);    //反序列化對象    return (T)serializer.Deserialize(fs);   }   catch (Exception e)   {    if (loggingEnabled)    {     //文件異常,寫入日志     LogLoadFileException(fileName, e);     return null;    }    else    {     throw new Exception(e.Message);    }   }   finally   {    if (fs != null) fs.Close();   }  }  /// <summary>  /// 序列化一個對象到文件中.  /// </summary>  /// <typeparam name="T"></typeparam>  /// <param name="fileName">文件名</param>  /// <param name="data">待序列化的數據</param>  /// <returns>  /// 如果日志啟用,則發生異常時,異常寫入日志,若日志沒有開啟,則直接拋出異常信息  /// loggingEnabled==true: log exception  /// loggingEnabled==false: throw exception  /// </returns>  public static void SaveToXml<T>(string fileName, T data) where T : class  {   SaveToXml(fileName, data, true);  }  /// <summary>  /// 文件反序列化,若發生異常,異常信息寫入日志  /// </summary>  /// <typeparam name="T"></typeparam>  /// <param name="fileName">文件名</param>  /// <param name="data">發序列化對象</param>  /// <param name="loggingEnabled">是否啟用日志</param>  public static void SaveToXml<T>(string fileName, T data, bool loggingEnabled) where T : class  {   FileStream fs = null;   try   {    var serializer = new XmlSerializer(typeof(T));    fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);    //序列化對象    serializer.Serialize(fs, data);   }   catch (Exception e)   {    if (loggingEnabled) LogSaveFileException(fileName, e);    else    {     throw new Exception(e.Message);    }   }   finally   {    if (fs != null) fs.Close();   }  }  /// <summary>  /// 序列化  /// XML & Datacontract Serialize & Deserialize Helper  /// </summary>  /// <typeparam name="T">T指定必須為class類型</typeparam>  /// <param name="serialObject"></param>  /// <returns></returns>  public static string XmlSerializer<T>(T serialObject) where T : class  {   var ser = new XmlSerializer(typeof(T));   //MemoryStream實現對內存的讀寫,而不是對持久性存儲器進行讀寫   //MemoryStream封裝以無符號字節數組形式存儲的數據,該數組在創建MemoryStream對象時被初始化,   //或者該數組可創建為空數組??稍趦却嬷兄苯釉L問這些封裝的數據。   //內存流可降低應用程序中對臨時緩沖區和臨時文件的需要。   var mem = new MemoryStream();   var writer = new XmlTextWriter(mem, UTF8);   ser.Serialize(writer, serialObject);   writer.Close();   return UTF8.GetString(mem.ToArray());  }  /// <summary>  /// 反序列化  /// </summary>  /// <typeparam name="T"></typeparam>  /// <param name="str"></param>  /// <returns></returns>  public static T XmlDeserialize<T>(string str) where T : class  {   var mySerializer = new XmlSerializer(typeof(T));   var mem2 = new StreamReader(new MemoryStream(UTF8.GetBytes(str)), UTF8);   return (T)mySerializer.Deserialize(mem2);  }  /// <summary>  ///   /// </summary>  /// <typeparam name="T"></typeparam>  /// <param name="xmlData"></param>  /// <returns>返回值類型為傳入的類型</returns>  public static T DataContractDeserializer<T>(string xmlData) where T : class  {   var stream = new MemoryStream(UTF8.GetBytes(xmlData));   var reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());   var ser = new DataContractSerializer(typeof(T));   var deserializedPerson = (T)ser.ReadObject(reader, true);   reader.Close();   stream.Close();   return deserializedPerson;  }  /// <summary>  ///   /// </summary>  /// <typeparam name="T"></typeparam>  /// <param name="myObject"></param>  /// <returns></returns>  public static string DataContractSerializer<T>(T myObject) where T : class  {   var stream = new MemoryStream();   var ser = new DataContractSerializer(typeof(T));   ser.WriteObject(stream, myObject);   stream.Close();   return UTF8.GetString(stream.ToArray());  }  /// <summary>  /// 序列化時異常日志  /// </summary>  /// <param name="fileName">文件名</param>  /// <param name="ex">異常</param>  [Conditional("TRACE")]  private static void LogLoadFileException(string fileName, Exception ex)  {   var sb = new StringBuilder();   sb.Append("Fail to load xml file: ");   sb.Append(fileName + Environment.NewLine);   sb.Append(ex);   //寫入日志記錄中方法   // Logger.LogEvent(LogCategory, LogEventLoadFileException, sb.ToString());  }  /// <summary>  /// 反序列化時異常日志  /// </summary>  /// <param name="fileName">文件名</param>  /// <param name="ex">異常</param>  [Conditional("TRACE")]  private static void LogSaveFileException(string fileName, Exception ex)  {   var sb = new StringBuilder();   sb.Append("Fail to save xml file: ");   sb.Append(fileName + Environment.NewLine);   sb.Append(ex);  }  /// <summary>  /// 將xml字符串序列化為數據流(數據流編碼為ASCII,UTF8)  /// </summary>  /// <returns>字符串轉換到流</returns>  public static MemoryStream StringXmlToStream(string strXml,Encoding encod)  {   MemoryStream memoryStream = null;   try   {    Encoding encoding;    if (Equals(encod, ASCII))    {      encoding = new ASCIIEncoding();    }    else    {      encoding = new UTF8Encoding();     }    var byteArray = encoding.GetBytes(strXml);    memoryStream = new MemoryStream(byteArray);    memoryStream.Seek(0, SeekOrigin.Begin);    return memoryStream;   }   catch (IOException ex)   {    throw new IOException(ex.Message);   }   finally   {    if (memoryStream != null) memoryStream.Close();   }  } }

   以上的代碼就不做贅述,需要次代碼的可以使用。

五.總結:

    本文講解了C#2.0引入的泛型知識,主要包含泛型類、泛型接口、泛型委托,并且重點講解了泛型方法,已經泛型的約束分類。最后給了一些利用泛型方法操作xml的方法。希望以上的講解可以幫助到正在想學習的人。

以上就是本文的全部內容,希望對大家有所幫助,同時也希望多多支持VEVB武林網!


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色综合色综合久久综合频道88| 日韩视频精品在线| 久久久精品2019中文字幕神马| 欧美精品免费在线观看| 色七七影院综合| 精品无人区太爽高潮在线播放| 亚洲的天堂在线中文字幕| 久久久久久久久久久av| 成人激情视频免费在线| 亚洲成成品网站| 亚洲国产精品久久久久久| 日韩女优在线播放| 亚洲精品美女久久久| 97视频在线观看网址| 久久精品视频导航| 中文字幕亚洲欧美| 免费91麻豆精品国产自产在线观看| 日韩精品免费观看| 亚洲国产精品va在线看黑人| 欧美激情亚洲综合一区| 亚洲午夜av电影| 国产精品丝袜白浆摸在线| 久久久爽爽爽美女图片| 国产精品免费久久久久影院| 欧美日韩免费在线观看| 91人人爽人人爽人人精88v| 国产91免费观看| 狠狠躁夜夜躁人人爽天天天天97| 日韩欧美综合在线视频| 中国人与牲禽动交精品| 日韩av最新在线观看| 国产日韩欧美电影在线观看| 国产精品扒开腿做爽爽爽的视频| 久久精品国产久精国产一老狼| 久久国产精品偷| 福利一区福利二区微拍刺激| 中文字幕日韩欧美在线视频| 中文字幕精品久久久久| 亚洲精品99久久久久中文字幕| 国产精品久久久久久久久久小说| 91精品国产91久久久久久最新| 欧美极品少妇xxxxx| 精品无码久久久久久国产| 午夜精品蜜臀一区二区三区免费| 日韩中文字幕网址| 午夜精品久久久久久久男人的天堂| 精品中文字幕在线2019| 国产精品久久网| 久久精品国产综合| 亚洲va码欧洲m码| 国产精品一区专区欧美日韩| 精品久久久久久久久久久久久| 欧美xxxwww| 欧美一级免费看| 国产精品视频久久| 国产精品99久久99久久久二8| 成人疯狂猛交xxx| 国产精品国产福利国产秒拍| 欧美在线视频一区| 色多多国产成人永久免费网站| 国产精品video| 在线精品国产欧美| 琪琪亚洲精品午夜在线| 欧美特黄级在线| www.日韩欧美| 91精品国产91久久久久久最新| 色一情一乱一区二区| 97视频在线观看免费高清完整版在线观看| 最近更新的2019中文字幕| 8x拔播拔播x8国产精品| 永久555www成人免费| 国产亚洲一级高清| 在线日韩日本国产亚洲| 中文字幕欧美视频在线| 亚洲乱码一区二区| 91精品国产色综合久久不卡98| 亚洲精品第一国产综合精品| 992tv成人免费视频| 这里只有精品久久| 日韩在线观看网站| 日韩有码在线视频| 欧美激情久久久久| 久久99青青精品免费观看| 日韩欧亚中文在线| 国产美女精品视频| 91精品国产综合久久男男| 日韩高清a**址| 亚洲国产成人在线播放| 久久视频在线直播| 视频直播国产精品| 亚洲国产欧美日韩精品| 久久在线免费视频| 91情侣偷在线精品国产| 亚洲中国色老太| 欧美在线免费观看| 日本精品视频在线| 国产精品视频一区二区三区四| 亚洲成人精品久久久| 青青久久aⅴ北条麻妃| 久久久久女教师免费一区| 中文字幕欧美日韩| 国产精品777| 国产精品久久久久久久久免费看| 国产精品免费久久久久久| 欧亚精品在线观看| 精品小视频在线| 88国产精品欧美一区二区三区| 韩国三级日本三级少妇99| 久久久久久久久久久免费| 国产一区二区美女视频| 国外成人免费在线播放| 热久久免费视频精品| 一区三区二区视频| 欧美中文字幕在线视频| yellow中文字幕久久| 色综合天天狠天天透天天伊人| 久久久久久亚洲精品中文字幕| 国产丝袜一区视频在线观看| 日韩免费在线观看视频| www.久久久久| 国内免费久久久久久久久久久| 久久成人精品一区二区三区| 精品丝袜一区二区三区| 高潮白浆女日韩av免费看| 亚洲精品美女久久久久| 国产主播精品在线| 97超视频免费观看| 日本一区二区在线免费播放| 亚洲欧美日韩国产精品| 久久香蕉频线观| 欧美专区国产专区| 亚洲嫩模很污视频| 美日韩精品免费观看视频| 国产福利视频一区| 久久精品视频导航| 中文字幕精品久久久久| 中文字幕国产精品久久| 成人国产精品色哟哟| 国产小视频91| 亚洲国产成人在线视频| 91免费在线视频| 91丨九色丨国产在线| 91在线播放国产| 狠狠色狠色综合曰曰| 成人久久久久久| 国产精品高清免费在线观看| 亚洲综合社区网| 奇米影视亚洲狠狠色| 一区二区三区www| 亚洲精选中文字幕| 欧美激情一级精品国产| 曰本色欧美视频在线| 欧美激情精品久久久久久黑人| 成人精品福利视频| 亚洲美女精品久久| 国产成人精品优优av| 精品magnet| 国产福利精品av综合导导航| 欧美理论电影网| 日本亚洲精品在线观看| 日本韩国欧美精品大片卡二| 91成人在线播放| 国产精品亚洲片夜色在线| 久久青草福利网站|