一、泛型

假定我要写个公共的輸出传到主要参数的方式(无需泛型),由于万物皆目标的原因,我先界定一个方式show(object obj),如下边所显示:

        public static void Show(object obj)
        {
            Console.WriteLine(obj.ToString());
        }

实行这一方式

            int i = 1;  //装箱
            Show(i);

假如传到的是值种类,值类型转换为引用类型,我们知道会产生装箱,它是对特性的危害,想一想如果是个结合,就得数次实行装箱、开箱实际操作。如ArrayList类,ArrayList存储目标,Add()方式界定为必须把一个目标做为主要参数,假如传到的值种类,就得装箱,在载入ArrayList中的值时,又得开展开箱,如下边编码所显示:

            var list = new ArrayList();
            list.Add(1); //装箱

            foreach (int i in list)
            {
                Console.WriteLine(i); //开箱
            }

假如应用泛型,就不容易出現那样的难题了,大家应用List<T>类来更新改造上边编码:

            var list = new List<int>();
            list.Add(1); 

            foreach (int i in list)
            {
                Console.WriteLine(i); 
            }

这儿就不会有装箱和开箱了,因此 我们在应用结合的情况下,尽可能应用泛型结合,不必应用非泛型结合。

二、种类安全性

在上面ArrayList类中,加上主要参数时,能够加上一切目标,例如上边的事例,假如在加上整数金额种类后再加上引用类型,那么做在编译程序时是沒有一切难题,可是在foreach句子应用整数金额种类迭代更新的情况下便会出错。

            var list = new ArrayList();
            list.Add(1); //装箱
            list.Add("string");

            foreach (int i in list)
            {
                Console.WriteLine(i);
            }

此刻便会报InvalidCastException的出现异常。

假如应用泛型结合List<T>的情况下去调用上边的编码,在编译程序的情况下便会出错。因此 这个地方大家就能了解,泛型是在编译程序时就早已实行了,因此 系统软件运作时大家时沒有装箱开箱的系统软件花销,并非泛型是在运作时实行的,因此 很有可能造成 出现异常产生;

三、建立泛型类和泛型方法

泛型方法,从我最开始第一个事例Show(object)  ,选用泛型来调用,界定为Show<T>(T);

        public static void Show<T>(T obj)
        {
            Console.WriteLine(obj.ToString());
        }

 泛型类,如public class List<T>{}

3.1 取名承诺

  •       泛型类型的名字用英文字母T做为作为前缀。
  •       要是没有独特的规定,泛型类型运作用随意类取代,且只使有一个泛型类型,就可以用标识符T做为泛型类型的名字。
  •       假如泛型类型有独特的规定(如它务必完成一个插口或继承自基类),或是应用了2个或之上的泛型类型,就应给泛型类型应用说明性的名字:

      public delegate void EventHandler<TEventArgs>(object sender,TEventArgs e);

      public delegate TOutput Convert<TInput,TOutput>(TInput input);

      public class SortedList<TKey,TValue>{};

3.2 初始值

     在泛型类和泛型方法中造成的一个难题是,在事先不明下列状况时,如何把初始值分派给参数化设计种类 T,给出参数化设计种类 T 的一个自变量 t,仅有当 T 为引用类型时,句子 t = null 才合理;仅有当 T 为标值种类而不是构造时,句子 t = 0 才可以一切正常应用。 解决方法是应用 default 关键词,此关键词针对引用类型会回到 null,针对标值种类会回到零。 针对构造,此关键词将回到复位为零或 null 的每一个构造组员。

应用方法如:T obj=default(T);

3.3 管束

在界定泛型类时,能够对手机客户端编码可以在实例化类时用以种类主要参数的种类类型释放限定。 假如手机客户端编码试着应用某一管束所不允许的种类来实例化类,则会造成编译程序时不正确。 这种限定称之为管束。 管束是应用where前后文关键词特定的。  下表列出了六种种类的管束:

管束   表明
where T:struct   针对构造的管束,种类T务必是值种类。
where T:class   类的管束,种类T务必是运用种类。
where T:<插口名字> 种类主要参数务必是特定的插口或完成特定的插口。 能够特定好几个插口管束。 管束插口还可以是泛型的。
where T:<基类名> 种类主要参数务必是特定的基类或继承自特定的基类。
where T:new()     种类主要参数务必具备无主要参数的公共性构造方法。 当与别的管束一起应用时,new() 管束务必最终特定。
where T1:T2           种类T1务必是种类T2或继承自泛型类型T2,该管束也称之为裸型管束。

 

 

 

 

 

 

 

 

    public class MyClass<T> where T : IComparer<T>, new()
    {

    }

上边编码,应用泛型类型加上了2个管束,申明特定种类T务必完成了IComparer插口,且务必有一个默认设置构造方法

    public class MyClass<TOutput, TInput> where TOutput : IComparer<TOutput>, new()
        where TInput:class,TOutput
    {

    }

上边编码用了2个泛型类型,TOutput务必完成了IComparer插口,且务必有一个默认设置构造方法,TInput务必是引用类型,且种类务必是TOutput或继承自TOutput。

3.4 承继

泛型类型能够完成泛型插口,还可以继承自一个类。泛型类型能够继承自泛型基类,其规定务必反复插口的泛型类型,或是务必特定基类的种类。如下述所显示:

    public class BaseClass<T> { }

    ///务必反复插口\基类的泛型类型
    public class MyClass<T> : BaseClass<T> { }
    public class BaseClass<T> { }

    ///务必特定基类的种类
    public class MyClass<T> : BaseClass<String> { }

派生类能够是泛型类或者非泛型类,比如界定一个抽象性的泛型基类,它在派生类中用一个实际的种类完成,如下述所显示:

    public abstract class Calcu<T>
    {
        public abstract T Add(T x, T y);

        public abstract T Sub(T x, T y);
    }

    /// <summary>
    /// 派生类中实际的种类完成
    /// </summary>
    public class IntCalcu : Calcu<int>
    {

        public override int Add(int x, int y)
        {
            return x   y;
        }

        public override int Sub(int x, int y)
        {
            return x - y;
        }
    }

四、总结

这种泛型类和泛型方法将一个或好几个种类的特定延迟到手机客户端编码申明并实例化此类或方式的情况下。 比如,根据应用泛型类型主要参数 T,您能够撰写别的手机客户端编码可以应用的单独类,而不至于导入运作时强制转换或装箱实际操作的成本费或风险性。在构架中有句话是让一切能延迟时间的延迟时间。