zoukankan      html  css  js  c++  java
  • 【转帖】为什么使用泛型

    原帖:http://blog.csdn.net/jecray/archive/2007/04/13/1563978.aspx

     有好久一段时间,我经常使用.net 1.1开发程序,发现.net 1.1缺少类似c++中的模板功能。这种支持类型参数的功能可以使我们设计一个有泛型的类,在运行时检测实际的类型。

    这样意味着用一个泛型参数T,你可 以写一个MyList<T>类,在使用MyList<int>, MyList<string> MyList<MyClass>时不需要担心在运行时进行转换或装箱操作。

    .NET 2.0引入了一个新的名字空间 System.Collections.Generic,他包括了支持泛型的类,例如:List, Queue, Stack, LinkedList。利用他们可以使你的程序更加有效率。

    泛型的优点

    .NET 2.0之前,泛型是通过 将特定类型和基类System.Object相互转换实现的。这种方法具有很大的局限性,比如ArrayListArrayList是一个非常好用 的集合类,可以随意存储任何值类型和引用。

    ArrayList list1 = new ArrayList(); 
        list1.Add(
    3); 
        list1.Add(
    105); 
        
    //...
        ArrayList list2 = new ArrayList();
        list2.Add(
    "First item."); 
        list2.Add(
    "Second item");
        
    //...

    但是这种便利是以性能为代价的,任何被加到ArrayList的引用或值都被显示地转换成System.Object。如果那些项是 值类型,他们在加入时必须装箱,在取出时拆箱。类型转换,装箱,拆箱操作降低了性能,特别在需要对一个大的集合进行拆装箱时,性能的损耗是巨大的。

    所以我们需要一个灵活的ArrayList同时提供更好的性能和支持多种类型。是否可以为ArrayList添加一个类型参 数呢?这正式泛型所提供的。泛型可以避免把所有项转换成Object,也可以使编辑器做类 型检查。

    Sytem.Collections.Generic中的List<T>进行相 同的操作:

    List<int> list1 = new List<int>();
        list1.Add(
    3); //不需要装箱和类型转换
        list1.Add("First item"); // 编译时错误

    List<T>ArrayList使用的不同只是 在声明和实例化时多了一个类型参数。而换来的好处是创建的List不但比ArrayList安全,而且速度要快,特别是在List中 存储值类型的时候。

    泛型类

    泛型类将操作封装成不针对特有的数据类型。泛型类最普遍的用法是实现linked lists, hash tables, stacks, queues, trees等,他们是以 相同的方式添加删除项而不关心项的数据类型。

    public class Node <T>
        
    {
            T head;
            T next;
        }

    这里T是一个类型参数,我们可以设置成 任何数据类型。

    这个类可以这样实例化

    Node<string> node = new Node<string>();

    这样就告诉编译器headnext属性是string

    泛型方法

    将一个方法加上类型参数的声明就是泛型方法。

    void Swap<T>ref T left, ref T right)
        
    {
            T temp;
            temp 
    = left;
            left 
    = right;
            right 
    = temp;
        }

    我们可以这样调用他

    int a = 1;
    int b = 2;
    Swap 
    <int> (a, b);

    你可以忽略类型参数因为编译器会自动加上,下面方法调用依旧是正确的:

    Swap (a, b);

    设计自己的泛型类
    下面的例子实现了一个泛型linked list

    using System;
    using System.Collections.Generic;
    public class MyList<T> //type parameter T in angle brackets
    {
        
    private Node head;
        
        
    // The nested class is also generic on T.
        private class Node 
        
    {
            
    private Node next;
            
    //T as private member data type:
            private T data; 
            
    //T used in non-generic constructor:
            
            
    public Node(T t) 
            
    {
                next 
    = null;
                data 
    = t;
            }

            
    public Node Next
            
    {
                
    get return next; }
                
    set { next = value; }
            }

     
            
    //T as return type of property:
            public T Data 
            
    {
                
    get return data; }
                
    set { data = value; }
            }

        }

     
        
    public MyList()
        
    {
            head 
    = null;
        }

     
        
    //T as method parameter type:
        public void AddHead(T t) 
        
    {
            Node n 
    = new Node(t);
            n.Next 
    = head;
            head 
    = n;
        }

     
        
    public IEnumerator<T> GetEnumerator()
        
    {
            Node current 
    = head;
            
    while (current != null)
            
    {
                
    yield return current.Data;
                current 
    = current.Next;
            }

        }


    }

    注意上面类的声明

    public class MyList<T>

    T是类 型参数,在上面的代码中,Node的数据类型是T而不是intstring或其他。这样使程序员 方便地用这个类处理任何数据类型。

    以下代码告诉我们如何用泛型类MyList<T>创建一个int list,只需简单的改 变类型参数,下面的代码就可以创建string list或其他自定义类型的list

    class Program
        
    {
            
    static void Main(string[] args)
            
    {
                
    //int is the type argument.
                MyList<int> list = new MyList<int>(); 

                
    for (int x = 0; x < 10; x++)
                    list.AddHead(x);
     
                
    foreach (int i in list)
                    Console.WriteLine(i);
                
                Console.WriteLine(
    "Done");
            }

        }

    泛型可以使类具有重用性,类型安全和效率,泛型在集合中广泛的使用。

    http://blog.csdn.net/chimomo/archive/2009/09/30/4620379.aspx

    在 C#中,使用泛型会获得以下优势:

    1. 减少装箱和拆箱操作,提高性能
    2. 可以进行编译时类型检查

    举 例说明:

    使 用非泛型的集合类,利用 .NET Framework 基类库中的 ArrayList 集合类。ArrayList 是一个使用起来非常方便的集合类,无需进行修改即可用来存储任何引用或值类型。

    1. // The .NET Framework 1.1 way to create a list:  
    2. System.Collections.ArrayList list1 = new System.Collections.ArrayList();  
    3. list1.Add(8);  
    4. list1.Add("It is raining heavily outside.");  

    但 这种方便是需要付出代价的。添加到 ArrayList 中的任何引用或值类型都将隐式地向上强制转换为 Object。 如果项是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行取消装箱操作。强制转换以及装箱和取消装箱操作都会降低性能;尤其是在必须对大型 集合进行循环访问的情况下,装箱和取消装箱的影响将非常明显。

    另 一个限制是缺少编译时类型检查;因为 ArrayList 将把所有项都强制转换为 Object, 所以在编译时无法防止客户端代码执行以下操作:

    1. System.Collections.ArrayList list = new System.Collections.ArrayList();  
    2. // Add an integer to the list.  
    3. list.Add(8);  
    4. // Add a string to the list. This will compile, but may cause an error later.  
    5. list.Add("It is raining heavily outside.");  
    6.   
    7. int t = 0;  
    8. // This causes an InvalidCastException to be returned.  
    9. foreach (int x in list)  
    10. {  
    11.     t += x;  
    12. }  

    尽 管将字符串和 int 组合在一个 ArrayList 中的做法在创建异类集合时是完全合法的,有时是有意图的,但这种做法更可能产生编程错误,并且直到运行时才能检测到此错误。

    在 C# 语言的 1.0 和 1.1 版本中,只能通过编写自己的特定于类型的集合来避免 .NET Framework 基类库集合类中的通用代码的危险。当然,由于此类不可对多个数据类型重用,因此将丧失通用化的优点,并且您必须对要存储的每个类型重新编写该类。

    ArrayList 和其他相似类真正需要的是:客户端代码基于每个实例指定这些类要使用的具体数据类型的方式。这样将不再需要向上强制转换为 T:System.Object, 同时,也使得编译器可以进行类型检查。换句话说,ArrayList 需要一个 type parameter。这正是泛型所能提供的。在 N:System.Collections.Generic 命名空间的泛型 List<T> 集合中,向该集合添加项的操作类似于以下形式:

    1. // The .NET Framework 2.0 way to create a list  
    2. List<int> list1 = new List<int>();  
    3.   
    4. // No boxing, no casting:  
    5. list1.Add(8);  
    6.   
    7. // Compile-time error:  
    8. // list1.Add("It is raining heavily outside.");  

    对于客户端代码,与 ArrayList 相比,使用 List<T> 时添加的唯一语法是声明和实例化中的类型参数。虽然这稍微增加了些编码的复杂性,但好处是您可以创建一个比 ArrayList 更安全(由于指定了Type,所以可以进行编译时类型检查)并且速度更快(由于对于值类型无需进行装箱拆箱操作)的列表,特别适用于列表项是值类型的情 况。

     

  • 相关阅读:
    Spring MVC Ajax 嵌套表单数据的提交
    Spring MVC 过滤静态资源访问
    Spring MVC 页面跳转时传递参数
    IDEA Maven 三层架构 2、运行 springMVC
    IDEA Maven 三层架构 1、基本的Archetype 搭建
    EasyUI DataGrid 基于 Ajax 自定义取值(loadData)
    Spring MVC Ajax 复杂参数的批量传递
    Mybatis Sql片段的应用
    在 Tomcat 8 部署多端口项目
    自动升级的设计思路与实现
  • 原文地址:https://www.cnblogs.com/cubean/p/1744354.html
Copyright © 2011-2022 走看看