• 【转帖】为什么使用泛型


    原帖: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,所以可以进行编译时类型检查)并且速度更快(由于对于值类型无需进行装箱拆箱操作)的列表,特别适用于列表项是值类型的情 况。

     

  • 相关阅读:
    cordova windows环境配置
    javascript 变量声明 和 作用域
    javascript 数组总结
    处理事件的兼容写法
    javascript 闭包
    事件委托和事件绑定
    依赖注入
    .Net委托
    sql游标循环结果集
    T-Sql之集合
  • 原文地址:https://www.cnblogs.com/cubean/p/1744354.html
Copyright © 2020-2023  润新知