• 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
  • 相关阅读:
    【leetcode】1365. How Many Numbers Are Smaller Than the Current Number
    【leetcode】1363. Largest Multiple of Three
    【leetcode】1362. Closest Divisors
    【leetcode】1361. Validate Binary Tree Nodes
    【leetcode】1360. Number of Days Between Two Dates
    【leetcode】1359. Count All Valid Pickup and Delivery Options
    【leetcode】1357. Apply Discount Every n Orders
    【leetcode】1356. Sort Integers by The Number of 1 Bits
    ISE应用入门的一些问题
    DDR的型号问题
  • 原文地址:https://www.cnblogs.com/Winston/p/1159925.html
Copyright © 2020-2023  润新知