• 分析 C# 2.0 新特性 范型(Generics)


    分析 C# 2.0 新特性 -- 范型(Generics)
    作者:梁振[MS-MVP]
     
    范型是提高面向对象程序多态性设计衍生的。
    1,C# 多态性设计回顾和展望
    在引入范型这个概念之前,回顾一下1.0或1.1中关于的Object类型的定义:
    Object类型是.NET Framework中System.Object的一个别名,可以分配任何类型给Object类型的变量。
    通过object类型的引入,实现了.NET对于面向对象程序多态设计。
    因为Object本身是一个引用类型,是存放在Heap(堆)上的。对于其他引用类型和Object转换很容易实现。
    而值类型和Object类型转换需要引入两个用于object类型和值类型转换概念boxing和unboxing.
    (1)boxing 装包
      将转换一个值类型到Object类型,
      例如:int i = 1;            //存储在栈上
            object o = (object) i;//存储在堆上
      上面的代码在IL中将会是box [mscorlib]System.Int32
     将Int32和1同时装入一个Object对象中,结构如下:
     object[{Int32}-{1}];//前者表示boxing类型,后者表示其值
    (2)unboxing 拆包
     将一个已装包为Obect类型的值类型转换回值类型
     操作分为两部分组成:
     a,首先检查是否转换回的类型是装包的类型,如果不是抛出一个InvalidCastException运行时错误.
     b,复制Object类型中的值到目标值类型变量;
     例如:
       int i = 1;
          object o = (object) i; //boxing
          int j = (int)o         //unboxing
          //double d = (double)o ,出现运行时错误
     
    通过上面的可以看到在.NET Framework 1.0 中使用object对象设计的多态性比C++的template(一种基于类似宏的编
    译时替换)执行效率增加了大量的copy的开销。所以在.NET Framewrok 2.0中引入范型来提高高面向对象程序多态性
    设计。

    2,范型概念和特点:
    范型的设计是为了解决上面提到过的Object的多态性设计中的两个问题:
    (1),性能上面的,boxing和unboxing需要大量的复制开销;
    (2),安全性上面的,在上面一个例子看到了如果unboxing类型不同会抛出一个InvalidCastException异常;
    范型的设计格式是使用<和>封闭其中一个范型参数,例如:
    public class Stack<T>;
    范型的实例化格式是使用需要使用的类型替换<和>封闭其中一个范型参数,例如:
    Stack<char> char_Stack = new Stack<char>();
    多范型类定义格式,在<和>封闭多个范型参数,例如:
    class Node<K,T>
    对于C++程序员,看上面关于范型的格式很快联系到了ISO C++当中的Template;
    的确两者语法上面非常相似,但是两者的多态性编译和实现有很大不同.
    在C++的Template编译后,没有编译带有Template的代码.而是通过一种宏的方式进行的替换过程.
    每次使用Template类型,编译器都会生成一个对应的类型代码.而不管是否个类型代码已经使用过了.
    在C#2.0中范型是在中间语言(IL)和公共语言运行时(CLR)支持的.
    对于值类型:会在JIT编译时候替换参数类型,如果存在以及编译特定类型的机器代码,将直接返回这段代码.
    这样避免了在ISO C++中Template可能带来代码膨胀.
    对于引用类型:会直接在JIT编译时候替换参数类型.
    理解C# 2.0范型是在实现是基于CLR支持的很重要啊,因为.NET的本质是和语言无关的.任何语言最后都是编译为中
    间语言,这样基于IL和CLR支持的范型可以运用到所有基于CLR实现的语言,例如:Visual Basic 2005等等.
    3,范型和其他类型执行效率对比例子
    下面分别是使用Int,Object和范型构造的3个栈的类
     /// <summary>
     /// Int类型实现的栈
     /// </summary>
     class IntStack
     {
      private int[] data;
      private int current;
      private int length;
      public IntStack(int Length)
      {
       length = Length;
       current = 0;
       data = new int[length];
      }
      public int Top()
      {
       return data[current - 1];
      }
      public void Push(int Data)
      {
       if (current < length)
       {
        data[current++] = Data;
       }
      }
      public void Pop()
      {
       if (current > 0)
       {
        current--;
       }
      }
     }
     /// <summary>
     /// 范型的栈
     /// </summary>
     /// <typeparam name="T">范型</typeparam>
     class TemplateStack<T>
     {
      private int length;
      private int current;
      private T[] data;
      public TemplateStack(int Length)
      {
       current = 0;
       length = Length;
       data = new T[length];
      }
      public T Top()
      {
       return data[current - 1];
      }
      public void Push(T Data)
      {
       if (current < length)
       {
        data[current++] = Data;
       }
      }
      public void Pop()
      {
       if (current > 0)
       {
        current--;
       }
      }
     }
     /// <summary>
     /// Object的栈
     /// </summary>
     class ObjectStack
     {
      private object[] data;
      private int current;
      private int length;
      public ObjectStack(int Length)
      {
       length = Length;
       current = 0;
       data = new object[length];
      }
      public object Top()
      {
       return data[current-1];
      }
      public void Push(object Data)
      {
       if (current < length)
       {
        data[current++] = Data;
       }
      }
      public void Pop()
      {
       if (current > 0)
       {
        current--;
       }
      }
     }
    通过测试直接使用Int的栈和范型构造Int栈的开销接近.
    而比较前面两个Object每增加一次unboxig开销是增加的2倍.

    4,附录.NET 2.0 Framework 范型容器列表:
    Comparer<T>      Comparer   比较
    Dictionary<K,T>     HashTable  hash表
    LinkedList<T>         LinkList   链表
    List<T>               ArrayList  数组链表
    Queue<T>              Queue    队列
    SortedDictionary<K,T> SortedList 排序链表
    Stack<T>              Stack    栈
    ICollection<T>  ICollection    容器接口
    IComparable<T>  System.IComparable比较接口
    IDictionary<K,T>  IDictionary    字典接口
    IEnumerable<T>  IEnumerable    枚举接口
    IEnumerator<T>  IEnumerator    跌代接口
    IList<T>  IList          链表接口
     
    参考资料:
    《Design and Implementation of Generics for the .NET Common Language Runtime》 
      ---Andrew Kennedy Don Syme (Microsoft Research, Cambridge, U.K.)
    《An Introduction to C# Generics》
      ---Juval Lowy IDesign (MSDN Online)
    《C# Programmer's Reference》
      ---MSDN Library  (MSDN Online)
  • 相关阅读:
    Adding a prefix header to an iOS project
    DZ论坛常见基本设置问题
    DZ论坛如何去掉“今日”“昨日”发帖数显示?
    Discuz源码
    怎样使Firefox的新建标签页为空白页
    discuz论坛
    TK域名首次注册教程(咸干花生)
    氪星年货 #1:那些来自大牛的真知灼见
    慢性子
    life and penis
  • 原文地址:https://www.cnblogs.com/goody9807/p/937665.html
Copyright © 2020-2023  润新知