泛型(一)简介

纯属复习笔记,小总结:文字较多排版很糟糕的随笔,岁很难赏心悦目,但也知识啊,读书得细心看,仔细看,不能被披着文字的纸老虎给吓住,也不要被千篇一眨眼就过了

知识点梳理:

1.概述
 
熟悉面向对象编程的开发人员都深谙这种编程方式的好处,其中一好处就是"代码重用",他极大的提高了开发效率,也就是说它可以派生一个类,让它继承基类的所有能力,派生类只需重写虚方法,或添加一些新方法,就可以定制派生类的行为。
 
2.泛型快速入门
泛型:英文generic,-->对应的命名空间 System.Collections.Generic
泛型是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”。
简单的说开发人员先定义好一个算法,比如排序、搜索、交换、比较或者转换等,但是定义算法的开发人员并不设定该算法要操作什么类型的数据:该算法可以广泛的应用于不同类型的对象。然后,另一个开发人员只要指定了算法要操作的具体数据类型,就可以开始使用这个现成的算法了。
例如,可用一个排序算法来操作Int32和String等类型的对象,或者用比较算法类操作Datetime和Version等类型的对象。
大多数的算法都封装在一个类型中,CLR允许创建泛型引用类型和泛型值类型,但不允许创建泛型枚举类型,除此之外,CLR还允许创建泛型接口和泛型委托。
方法偶尔也封装有用的算法,所以CLR允许在引用类型、值类型或接口中定义泛型方法
 
先看以简单例子
Framework Class Library定义了一个泛型列表算法,List<T>(读list of Tee),以下是精简过的源代码
[Serializable]
public class List<T>:IList<T>,ICollection<T>,IEnumerable<T>,IList,ICollection,Enumerable{
    public List();
    public void Add(T item);
    public Int32 BinarySearch(T item);
    public void Clear();
    public Boolean Contains(T item);
    public void Sort();
    public void Sort(IComparer<T> comparer);
    public void Sort(Comparison<T> comparison)
    public T[] ToArray();
    public Int32 Count{ get; }
    public T this[Int32 index] { get;set; }
}

 

这里的T是种可以是任何变量的类型:专业术语->类型参数
 
Tip:MS的设计原则,泛型参数变量要么称之为T,要么至少以大写T开头(如TKey和TValue)
 
定义好泛型List<T>类型后,使用泛型类型或方法,指定的具体的数据类型称为类型参数(type argument)
 
泛型为开发人员提供以下优势:
1.源代码保护:不需要访问算法的源代码。
2.类型安全:若试图使用不兼容类型的一个对象,会造成编译时出错。
3.更加清晰的代码:由于强制类型安全,减少了转型次数。
4.更佳的性能:在有泛型之前,要想定义一个常规化的算法,他的所有成员要定义成Object数据类型。要用这个算法来操作值类型的实例,CLR必须在调用算法的成员之前对值类型实例进行装箱,装箱会造成在托管堆上的内存分配,从而造成更多的垃圾回收,进而损害程序的性能。
 
利用List算法和非泛型ArrayList算法性能比较
public static void ValueTypePerfTest() {
            const Int32 count = 10000000;
 
            using (new OperationTimer("List<Int32>"))
            {
                List<Int32> l = new List<Int32>(count);
                for ( Int32 n = 0;  n < count;  n++)
                {
                    l.Add(n);
                    Int32 x = l[n];
                }
                l = null;//确保进行垃圾回收
            }
 
            using (new OperationTimer("ArraryList of Int32"))
            {
                ArrayList a = new ArrayList();
                for (Int32 n = 0; n < count; n++)
                {
                    a.Add(n);
                    Int32 x = (Int32)a[n];
 
                }
                a = null;//确保进行垃圾回收
            }
        }
 
 public static void ReferenceTypePrefTest() {
            const Int32 count = 10000000;
 
            using (new OperationTimer("List<String>"))
            {
                List<String> l = new List<String>(count);
                for (Int32 n = 0; n < count; n++)
                {
                    l.Add("X");
                    String x = l[n];
                }
                l = null;//确保进行垃圾回收
            }
 
            using (new OperationTimer("ArraryList of Int32"))
            {
                ArrayList a = new ArrayList();
                for (Int32 n = 0; n < count; n++)
                {
                    a.Add("X");
                    String x = (String)a[n];
 
                }
                a = null;//确保进行垃圾回收
            }
        }
 
 internal sealed class OperationTimer : IDisposable {
        private Int64 m_startTime;
        private String m_text;
        private Int32 m_collectionCount;
 
        public OperationTimer(String text)
        {
            PrepareForOperation();
 
            m_text = text;
            m_collectionCount = GC.CollectionCount(0);
 
            //这应该是方法的最后一个语句,从而最大程度保证计时的准确性
            m_startTime = Stopwatch.GetTimestamp();
        }
 
        public void Dispose() {
            Console.WriteLine("{0,6:###.00} seconds (GCs={1,3})  {2}",
                (Stopwatch.GetTimestamp()-m_startTime)/
                    (Double)Stopwatch.Frequency,
                    GC.CollectionCount(0)-m_collectionCount,m_text
                );
        }
        private static void PrepareForOperation() {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }
 
    }

 
输入结果证明将泛型List算法应用于Int32类型速度将比非泛型块很多
 
Framework类库中的泛型
 
泛型最明显的应用就是集合类。FCL已经定义了几个泛型集合类。其中大多数都在System.Collections.Generic和System.Collections.ObjectModel命名空间中。要使用线程安全的泛型集合类,可以去System.Collections.Concurrent命名空间寻找。
MS建议开发人员使用泛型集合类,并基于几个方面的原因,不鼓励使用非泛型集合类。
首先,非泛型集合类不是泛型的,所以无法像使用泛型集合类那样,获得类型安全、更清晰的代码以及更佳的性能。
其次,泛型类具有比非泛型类更好的对象模型。例如,虚方法的数量显著减少,从而获得更好的性能,另外,泛型集合类增添了一些新成员,为开发人员提供新的功能。
 
新的泛型接口并不是设计用来玩去取代旧的非泛型接口。许多时候,为了保证向后兼容性,我们不得不同时使用两者。例如,如果List<T>类只实现了IList<T>接口,就没有代码能将一个List<DateTime>对象看成一个IList了。
还应该注意System.Array类提供了大量的静态泛型方法
例如:AsReadOnly,BinarySearch,ConverAll,Exists,Find,FindAll,FindIndex,FindLast,FindLastIndex,ForEach,IndexOf,LastIndexOf,Resize,Sort和TrueForAll等
下面代码如何使用其中的一些方法

Wintellect的Power Collections库
 
MS的要求,Wintellect制作了Power Collections库,使CLR程序员也能使用C++标准模版库(STL)的部分集合类,详情访问Wintellect.com
posted @ 2012-11-23 15:36  Lordbaby  阅读(303)  评论(0编辑  收藏  举报