泛型方法分析,泛型方法分析

   
C#2.0引入了泛型这一个特点,由于泛型的引入,在自然水准上硕大的增高了C#的生气,可以完成C#1.0时需要编制复杂代码才得以成功的一部分效益。可是作为开发者,对于泛型可谓是又爱又恨,爱的是其无坚不摧的效率,以及该特性带来的频率的擢升,恨的是泛型在纷繁的时候,会表现很是复杂的语法结构。这种复杂不仅是对此初学者,对于部分有付出经历的.NET开发者,也是一个不那么容易领悟的风味。

   
C#2.0引入了泛型这几个特点,由于泛型的引入,在一定水平上硕大的提升了C#的肥力,可以完成C#1.0时索要编制复杂代码才得以成功的有的功用。可是作为开发者,对于泛型可谓是又爱又恨,爱的是其强劲的职能,以及该特性带来的功能的升级换代,恨的是泛型在千头万绪的时候,会表现卓殊复杂的语法结构。这种复杂不仅是对于初学者,对于有些有开发经历的.NET开发者,也是一个不那么容易理解的表征。

   接下来我们来询问一下C#2.0参预的特色:泛型。

   接下来我们来询问一下C#2.0加盟的特征:泛型。

一.泛型的中坚特性概述:

   
在实际项目支付中,任何API只要将object作为参数类型和再次回到类型应用,就可能在某个时候关系强类型转换。提到强类型转换,估摸很多开发者第一反响就是“效率”这几个次,对于强类型的利害重要看使用者利用的环境,天底下没有绝对的坏事,也绝非断然的善举,有关强类型的问题不是此次的第一,不做重要介绍。

   
泛型是CLR和C#提供的一种特别体制,辅助另一种形式的代码重用,即“算法重用”。泛型实现了序列和方法的参数化,泛型类型和办法也足以让参数告诉使用者利用什么类型。

   
泛型所带动的补益:更好的编译时检查,更多在代码中能直接表现的消息,更多的IDE辅助,更好的习性。可能有人会疑窦,为何泛型会带来这么多好处,使用一个不可能分别不同门类的常规API,相当于在一个动态环境中走访异常API。

   
CLR允许制造泛型引用和泛型值类型,可是不同意创造泛型枚举,并且CLR允许创设泛型接口和泛型委托,CLR允许在引用类型、值类型或接口中定义泛型方法。定义泛型类型或艺术时,为品种指定了别样变量(如:T)都号称类型参数。(T是一个变量名,在源代码中可知运用一个数据类型的其他地点,都得以使用T)在C#中泛型参数变量要么成为T,要么至少一大写T开首。

一.泛型的中央特征概述:

   
在其实项目开支中,任何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);
  }

   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方法。假若定义的一个寄托项目指定了档次参数,编译器会定义委托类的法子,用指定的系列参数替换方法的参数类型和值类型。

 
 以上是对泛型类、泛型接口和泛型委托的简要询问,本文的目标关键是执教泛型方法,上边我们实际领会部分泛型泛型的知识。

   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列表。

 
将原始列表中的每个元素都转换成目的项目,将转移后的元素添加到一个列表中,最后回来这一个列表。以上的处理形式,首要将其泛型方法的参数举办依次的细化,无论在如何课程,都急需将复杂的题目展开简单化,将抽象的问题具体化,这也是一种常用的处理形式。

 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引入。

 2.类型约束:

   
约束的功效是限量能指定成泛型实参的档次数量。通过限制类型的数额,大家得以对那么些类型执行更多的操作。约束可以采纳于一个泛型类型的品类参数,也可以使用于一个泛型方法的门类参数。CLR不容许基于项目参数名称或约束进行重载,只好按照元数对品种或格局开展重载。不容许为重写方法的花色参数指定其他自律,但是项目实参的名称是可以更改的。

   
泛型约束的操作,约束要放权泛型方法或泛型类型阐明的最终,并由上下文关键where引入。

   (1).引用类型约束:

     
引用类型约束:用于确保使用的体系实参是引用类型。(表示为:T:class,且务必为项目参数指定的第一个约束。)

   (1).引用类型约束:

     
引用类型约束:用于确保使用的档次实参是引用类型。(表示为:T:class,且务必为品种参数指定的率先个约束。)

   (2).值类型约束:

     
值类型约束:用于确保使用的品种参数是指类型。(表示为:T:struct,可空类型不包含在内)

   (2).值类型约束:

     
值类型约束:用于确保使用的品类参数是指类型。(表示为:T:struct,可空类型不含有在内)

   (3).构造函数类型约束:

     
构造函授类型约束:指定所有类别参数的最终一个约束,它检查项目实参是否有一个可用以创立实例的无参构造函数。(表示为:T:new())适用于所有值类型,所有没有体现注明构造函数的非静态、非抽象类,所有显示注解了一个公共无参构造函数的非抽象类。

   (3).构造函数类型约束:

     
构造函授类型约束:指定所有类型参数的末尾一个束缚,它检查项目实参是否有一个可用以成立实例的无参构造函数。(表示为:T:new())适用于所有值类型,所有没有呈现讲明构造函数的非静态、非抽象类,所有显示讲明了一个公家无参构造函数的非抽象类。

   (4).转换类型约束:

   
 转换类型约束:允许你指定另一个门类,类型实参必须可以经过一致性、引用或装箱转换隐式地变换为该类型。仍是可以够规定类型实参必须能够转换为另一个档次实参。(例:class
山姆(Sam)ple<T> where T:Stream)

   (4).转换类型约束:

   
 转换类型约束:允许你指定另一个品种,类型实参必须可以由此一致性、引用或装箱转换隐式地更换为该项目。还足以确定类型实参必须可以变换为另一个品类实参。(例:class
山姆ple<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);

   (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对象时被初始化,
            //或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。
            //内存流可降低应用程序中对临时缓冲区和临时文件的需要。
            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();
            }



        }

    }

   以上的代码就不做赘述,需要次代码的可以应用。

四.泛型方法应用代码示例:

   以上讲解的关于泛型方法的情节,这里提供一个有关泛型方法操作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对象时被初始化,
            //或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。
            //内存流可降低应用程序中对临时缓冲区和临时文件的需要。
            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的办法。希望以上的上课可以扶助到正在想深造的人。

五.总结:

   
本文讲解了C#2.0引入的泛型知识,紧要含有泛型类、泛型接口、泛型委托,并且紧要教学了泛型方法,已经泛型的牢笼分类。最后给了有些应用泛型方法操作xml的法子。希望以上的上课能够帮助到正在想学习的人。

相关文章