• 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
  • 相关阅读:
    OpenCV-Python 模板匹配 | 三十一
    OpenCV-Python 傅里叶变换 | 三十
    OpenCV-Python 直方图-3:二维直方图 | 二十八
    OpenCV-Python 直方图-4:直方图反投影 | 二十九
    角谷猜想
    C# Notepad++ 环境配置
    C++ Notepad++ 环境配置
    字符串内无重复字符的最长子串长度
    计算给定字符串的无重复字符的最长子串长度
    黑色星期五
  • 原文地址:https://www.cnblogs.com/Winston/p/1159925.html
Copyright © 2020-2023  润新知