zoukankan      html  css  js  c++  java
  • 转载:C#中的泛型

    泛型类和泛型方法兼复用性、类型安全和高效率于一身,是与之对应的非泛型的类和方法所不及。泛型广泛用于容器(collections)和对容器操作的方 法中。.NET框架2.0的类库提供一个新的命名空间System.Collections.Generic,其中包含了一些新的基于泛型的容器类。要查 找新的泛型容器类(collection classes)的示例代码,请参见基础类库中的泛型。当然,你也可以创建自己的泛型类和方法,以提供你自己的泛化的方案和设计模式,这是类型安全且高效 的。下面的示例代码以一个简单的泛型链表类作为示范。(多数情况下,推荐使用由.NET框架类库提供的List<T>类,而不是创建自己的 表。)类型参数T在多处使用,具体类型通常在这些地方来指明表中元素的类型。

    针对早期版本的通用语言运行时和C#语言的局限,泛型提供了一个解决方案。以前类型的泛化(generalization)是靠类型与全局基类 System.Object的相互转换来实现。.NET框架基础类库的ArrayList容器类,就是这种局限的一个例子。ArrayList是一个很方 便的容器类,使用中无需更改就可以存储任何引用类型或值类型。

    但是这种便利是有代价的,这需要把任何一个加入ArrayList的引用类型或值类型都隐式地向上转换成System.Object。如果这些 元素是值类型,那么当加入到列表中时,它们必须被装箱;当重新取回它们时,要拆箱。类型转换和装箱、拆箱的操作都降低了性能;在必须迭代 (iterate)大容器的情况下,装箱和拆箱的影响可能十分显著。

    另一个局限是缺乏编译时的类型检查,因为无法对参数进行约束!

    若要检查表中的一个元素,以确定它是否合法或是否可以与其他元素相比较,那么编译器必须保证:客户代码中可能出现的所有类型参数,都要支持所需调用的操作 或方法。这种保证是通过在泛型类的定义中,应用一个或多个约束而得到的。一个约束类型是一种基类约束,它通知编译器,只有这个类型的对象或从这个类型派生 的对象,可被用作类型参数。一旦编译器得到这样的保证,它就允许在泛型类中调用这个类型的方法。上下文关键字where用以实现约束。

    同一个类型参数可应用多个约束。约束自身也可以是泛型类,如下:
     
    class MyList<T> where T: Employee, IEmployee,  IComparable<T>,  new()
    {…}
     
        下表列出了五类约束:
    约束
    描述
    where T: struct
    类型参数必须为值类型。
    where T : class
    类型参数必须为类型。
    where T : new()
    类型参数必须有一个公有、无参的构造函数。当于其它约束联合使用时,new()约束必须放在最后。
    where T : <base class name>
    类型参数必须是指定的基类型或是派生自指定的基类型。
    where T : <interface name>
    类型参数必须是指定的接口或是指定接口的实现。可以指定多个接口约束。接口约束也可以是泛型的。
     
     
    类型参数的约束,增加了可调用的操作和方法的数量。这些操作和方法受约束类型及其派生层次中的类型的支持。因此,设计泛型类或方法时,如果对泛型成员执行任何赋值以外的操作,或者是调用System.Object中所没有的方法,就需要在类型参数上使用约束。
     
    无限制类型参数的一般用法
    没有约束的类型参数,如公有类MyClass<T>{...}中的T, 被称为无限制类型参数(unbounded type parameters)。无限制类型参数有以下规则:
    l        不能使用运算符 != 和 == ,因为无法保证具体的类型参数能够支持这些运算符。
    l        它们可以与System.Object相互转换,也可显式地转换成任何接口类型。
    l        可以与null比较。如果一个无限制类型参数与null比较,当此类型参数为值类型时,比较的结果总为false。
     
     
    无类型约束
    当约束是一个泛型类型参数时,它就叫无类型约束(Naked type constraints)。当一个有类型参数成员方法,要把它的参数约束为其所在类的类型参数时,无类型约束很有用。如下例所示:
     
    class List<T>
    {
          //...
        void Add<U>(List<U> items) where U:T {…}
    }
     
    在上面的示例中, Add方法的上下文中的T,就是一个无类型约束;而List类的上下文中的T,则是一个无限制类型参数。
     
    无类型约束也可以用在泛型类的定义中。注意,无类型约束一定也要和其它类型参数一起在尖括号中声明:
    //naked type constraint
    public class MyClass<T,U,V> where T : V
     
    因为编译器只认为无类型约束是从System.Object继承而来,所以带有无类型约束的泛型类的用途十分有限。当你希望强制两个类型参数具有继承关系时,可对泛型类使用无类型约束。
     
     
    可以在一个类型指定多个接口作为约束,如下:
     
    class Stack<T> where T : IComparable<T>, IMyStack1<T>{}
     
     
    一个接口可以定义多个类型参数,如下:
     
    IDictionary<K,V>
     
    接口和类的继承规则相同:
    //Okay.
    IMyInterface : IBaseInterface<int>
    //Okay.
    IMyInterface<T> : IBaseInterface<T>
     
    //Okay.
    IMyInterface<T>: IBaseInterface<int>
    //Error.
    IMyInterface<T> : IBaseInterface2<T, U>
     
    具体类可以实现封闭构造接口,如下:
    class MyClass : IBaseInterface<string>
     
    泛型类可以实现泛型接口或封闭构造接口,只要类的参数列表提供了接口需要的所有参数,如下:
    //Okay.
    class MyClass<T> : IBaseInterface<T>
    //Okay.
    class MyClass<T> : IBaseInterface<T, string>
  • 相关阅读:
    【并发编程】多线程并发最佳实践
    【并发编程】死锁
    【并发编程】【JDK源码】J.U.C--线程池
    【并发编程】【JDK源码】J.U.C--组件FutureTask、ForkJoin、BlockingQueue
    【JVM】关于类加载器准备阶段的一道面试题目
    【并发编程】【JDK源码】J.U.C--AQS 及其同步组件(2/2)
    【并发编程】线程安全策略
    JSP 9大内置对象详解
    Jquery中的bind(),live(),delegate(),on()绑定事件方式
    阻止事件冒泡
  • 原文地址:https://www.cnblogs.com/tianboblog/p/5423014.html
Copyright © 2011-2022 走看看