泛型简介

来源:互联网 发布:知乎 保研 大四换导师 编辑:程序博客网 时间:2024/04/27 23:44
  有好久一段时间,我经常使用.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");
        }

    }

 

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