C#2.0中的泛型基础介绍

泛型简介
    泛型是C#2.0最为强大的特点之一。泛型使得我们定义类型安全(type-safe)的数据结构。因为我们可以重用数据处理的算法而无需关注数据的特定类型,从而提高开发效率和代码质量。从观念上讲,泛型类似欲C++中的模板,但是他们的实现和功能却有着很大的不同。

泛型问题描述
    假设一种常用的数据结构,例如stack,他提供的经典method比如push和pop。 当我们想要开发一个通用stack(genaral-purpose)的时候,我们会想利用这种stack能够处store任意类型的实例。在C#1.1中,我们只能用一个基于对象的(object-based) stack, 也就是在stack中的内部数据结构是不定型的(amorphous),然后stack 的method与objects进行交互。
比如
Public stack stack
{
obejct[] m_Items;
public void push(object item)
{...}
public object opo()
{...}
}
Stack mystack=new Stack();
mystack.push(1);
mystack.push(2);
int number=(int)stack.pop();


但是,对于基于对象的解决方法,存在2个问题。
    第一个问题是性能performance. 当我们利用值类型的时候,我们必须采用装箱操作(box) 将他们Push到stack中,当从stack中pop时,我们必须执行unbox操作,从而导致一些不必要的垃圾回收操作。即使我们用引用类型(reference type)而不是值类型,仍然会存在性能下降,因为其必须将其从一个对象转变成(cast)与其实际交互的类型,从而增加开销。
Stack mystack=new Stack();
mystack.push("1");
string number=(string)stack.pop();
       第二个问题是关于类型安全(type safety).因为编译器允许我们将任何类型转换成object或者将object转换cast)成任何类型。这样,我们便失去了编译时(compile-time)类型安全。例如,以下代码编译时没问题,但是执行时会抛出异常
stack mystack=new stack();
mystack.push(1);
string number=(string)stack.pop();
解决这个问题的方法是我们设计一种指定特定类型的stack.例如IntStack,StringStack等等。这样就失去了reuse的意义。

什么是泛型(Generics)
    泛型允许我们定义一种类型安全的类,同时兼顾类型安全,性能和效率。我们只需要实现一次泛型服务,然后你就可以利用任何类型来使用它。语法为 <and > 标记,来包装一个泛型类型参数。例如,下面的代码demonstrate如何定义和使用一个泛型stack

block 1: the implementation of generic stack
public class stack<T>
{
readonly int m_size;
int m_stackpointer=0;
T[] m_Items;
public stack(int size)
{
m_size=size;
m_Items=new T[m_size];
}
public void Push(T item)
{
    if(m_stackpointer>=m_size)
        throw new StackOverflowException();
    m_Items[m_stackpointer]=item;
    m_stackpointer++;
}

public T pop()
{
    m_stackpointer--;
    if(m_stackpointer>=0)
            return m_Items[m_stackpointer];
    else
        {
            m_stackpointer=0;
            throw new InvalidOperationException("cannot pop an empty stack");
        }

}
}


blcok 2: the use of specific-type stack
public class program
{
    public static void Man()
    {
        stack<int> mystack=new stack<int>();
        mystack.push(1);
        mystack.push(2);
        int numnber=mystack.pop();
}
}


泛型的益处
    .Net中的泛型允许我们重用代码,提高开发效率。即使改变数据类型或者内部数据,代码也不需要重写,不管是值类型或者是引用类型。我们只需要开发,测试,发布我们的代码一次后,我们就可以对任何的数据类型进行重用,包括未来未知的数据类型,所有编译器支持的和类型安全的即可。因为泛型代码不会强制执行装箱和拆箱操作,或者类型转换,因此performance得以提高。

泛型的应用
sample 1:单泛型
public struct Point<T>
{
   public T X;
   public T Y;
}
然后我们可以利用这个泛型点作为整数坐标点,例如
Point<int> point;
point.X=1;
point.Y=2;

多泛型
例如,以下是一个泛型的链表的示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GenericTest
{
    public class Node<K, I>
    {
        public K m_key;
        public I m_item;
        public Node<K,I> next;

        public Node()
        {
         
        }

        public Node(K key, I item)
        {
            m_item = item;
            m_key = key;
            next = null;
        }
    }

    public class List<K,I>
    {
        Node<K, I> m_listHead;
        Node<K, I> m_listTail;

        public List()
        {
            m_listHead = m_listTail = null;
        }

        public void InsertList(K key,I item)
        {
            Node<K, I> newNode = new Node<K, I>(key, item);
            if (m_listHead == null)
                m_listHead = newNode;
            else
                 m_listTail.next= newNode;
            m_listTail = newNode;
            m_listTail.next = null;
        }

        public void ShowList()
        {
            Node<K,I> p;
            p=m_listHead;
            while (p!=null)
            {
                Console.WriteLine("key:{0} item:{1}", p.m_key, p.m_item);
                p = p.next;
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\nGeneric List  1 test:");
           
List<int, string> mylist = new List<int, string>();
            mylist.InsertList(1, "herengang");
            mylist.InsertList(2, "guliqun");
            mylist.InsertList(4, "Herenchao");
            mylist.ShowList();

            List<DateTime, string> haha = new List<DateTime, string>();
            Console.WriteLine("\nGeneric List 2 test:");
            haha.InsertList(DateTime.Now, "AAA");
            haha.InsertList(DateTime.Today, "BBB");
            haha.ShowList();
        }
    }
}

//generic type aliasing 给泛型取别名
using List = LinkedList<int,string>;
class ListClient
{
static void Main(string[] args)
{
List list = new List();
list.AddHead(123,"AAA");
}
}
说明:该文章翻译自http://msdn2.microsoft.com/en-us/library/ms379564(VS.80).aspx

posted on 2008-04-18 14:40  飞天舞者  阅读(311)  评论(0编辑  收藏  举报

导航

For more information about me, feel free email to me winston.he@hotmail.com