C#個人總結,第5章:泛型

1. 概述

(1)泛型並不是一個全新的結構,其他語言中有類似的概念。例如,C++模板就與泛型相似。

1.1 性能

(1)對值類型使用非泛型集合類,在把值類型轉換爲引用類型,和把引用類型轉換爲值類型時,需要進行裝箱和拆箱操作。

(2)值類型存儲在棧上,引用類型存儲在堆上。C#類是引用類型,結構是值類。

(3)從值類型轉換爲引用類型稱爲裝箱。

1.2 類型安全

1.3 二進制代碼的重用

1.4 代碼的擴展

1.5 命名約定

  • 泛型類型的名稱用字母T作爲前綴。
  • 如果沒有特殊的要求,泛型類型允許用任意類替代,且只使用了一個泛型類型,就可以用字符T作爲泛型類型的名稱。
  • 如果泛型類型有特定的要求(例如,它必須實現一個接口或派生自鞠,或者使用了兩個或多個泛型類型,就應給泛型類型使用描述性的名稱:

2. 創建泛型類

(1)一個一般的、非泛型的簡化鏈表類,在鏈表中,一個元素引用下一個元素

代碼:

namespace study5_2
{
    //鏈表結點,包括前一個指針,後一個指針,以及當前值
    public class LinkedListNode
    {
        public object Value { get; private set; }

        public LinkedListNode Next { get; internal set; }
        public LinkedListNode Prev { get; internal set; }

        public LinkedListNode(object value)
        {
            this.Value = value;
        }
    }


    public class LinkedList:IEnumerable
    {
        public LinkedListNode First { get; private set; }//鏈表
        public LinkedListNode Last { get; private set; }//鏈尾

        public LinkedListNode AddLast(object node)
        {
            var newNode = new LinkedListNode(node);
            if (First == null)
            {
                First = newNode;
                newNode.Prev = Last;
                Last = First;
            }
            else
            {
                LinkedListNode previous = Last;
                Last.Next = newNode;
                Last = newNode;
                Last.Prev = previous;
            }
            return newNode;
        }


        public IEnumerator GetEnumerator()
        {
            LinkedListNode current = First;
            while(current!=null)
            {
                yield return current.Value;
                current = current.Next;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var list1 = new LinkedList();
            list1.AddLast(2);
            list1.AddLast(4);
            list1.AddLast("6");
            foreach (int i in list1)
            {
                Console.WriteLine(i);
            }

        }
    }
}
結果:


(2)鏈表的泛型版本:

代碼:

namespace study5_2
{
    //鏈表結點,包括前一個指針,後一個指針,以及當前值
    public class LinkedListNode<T>
    {
        public T Value { get; private set; }

        public LinkedListNode<T> Next { get; internal set; }
        public LinkedListNode<T> Prev { get; internal set; }

        public LinkedListNode(T value)
        {
            this.Value = value;
        }
    }


    public class LinkedList<T>:IEnumerable<T>
    {
        public LinkedListNode<T> First { get; private set; }//鏈表
        public LinkedListNode<T> Last { get; private set; }//鏈尾

        public LinkedListNode<T> AddLast(T node)
        {
            var newNode = new LinkedListNode<T>(node);
            if (First == null)
            {
                First = newNode;
                newNode.Prev = Last;
                Last = First;
            }
            else
            {
                LinkedListNode<T> previous = Last;
                Last.Next = newNode;
                Last = newNode;
                Last.Prev = previous;
            }
            return newNode;
        }


        public IEnumerator<T> GetEnumerator()
        {
            LinkedListNode<T> current = First;
            while(current!=null)
            {
                yield return current.Value;
                current = current.Next;
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var list1 = new LinkedList<int>();
            list1.AddLast(2);
            list1.AddLast(4);
            list1.AddLast(6);
            foreach (int i in list1)
            {
                Console.WriteLine(i);
            }

        }
    }
}

結果:

3. 泛型類的功能

(1)代碼

namespace study5_3
{
    public interface IDocument
    {
        string Title { get; set; }
        string Content { get; set; }
    }

    public class Document:IDocument
    {
        public string Title { get; set; }
        public string Content { get; set; }
        public Document()
        {

        }
        public Document(string title, string content)
        {
            this.Title = title;
            this.Content = content;
        }
    }
    public class DocumentManager<T>
    {
        private readonly Queue<T> documentQueue = new Queue<T>();

        public void AddDocument(T doc)
        {
            lock(this)
            {
                documentQueue.Enqueue(doc);
            }

        }
        public bool IsDocumentAvailable
        {
            get { return documentQueue.Count > 0; }
        }

        public T GetDocument()
        {
            T doc = default(T);
            lock(this)
            {
                doc = documentQueue.Dequeue();
            }
            return doc;
        }

        public void DisplayAllDocuments()
        {
            foreach(T doc in documentQueue)
            {
                Console.WriteLine(((IDocument)doc).Title);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var dm = new DocumentManager<Document>();
            dm.AddDocument(new Document("Title A", "Sample A"));
            dm.AddDocument(new Document("Title B", "Sample B"));

            dm.DisplayAllDocuments();

            if(dm.IsDocumentAvailable)
            {
                Document d = dm.GetDocument();
                Console.WriteLine(d.Content);
            }
        }
    }
}

(2)結果


3.1 默認值

(1)現在給DocumentManager<T>添加一個GetDocument()方法。在這個方法中,應把類型T指定爲null。但是,不能把null 賦予泛型類型。原因是泛型類型也可以實例化爲值類型,而null只能用於引用類型。爲了解決這個問題,可以使用default關鍵字。通過default關鍵字,將null賦予引用類型,將0賦予值類型。

3.2 約束

(1)泛型支持幾種約束類型


3.3 繼承

(1)泛型類型可以實現泛型接口,也可以派生自一個類。泛型類可以派生自泛型基類:
public class Base<T>
{
}
public class Derived<T> : Base<T>

{

}

3.4 靜態成員

(1)泛型類的靜態成員只能在類的一個實例中共享。下面StaticDemo<T>類包含靜態字段x:
public class StaticDemo<T>
{
       public static int x;
}

4. 泛型接口

(1)使用泛型可以定義接口,在按口中定義的方法可以帶泛型參數。

4.1 協變和抗變

(1).NET4通過協變和抗變爲泛型接口和泛型委託添加了一個重要的擴展。協變和抗變指對參數和返回值的類型進行轉換。

4.2 泛型接口的協變

(1)如果泛型類型用out關鍵字標註,泛型接口就是協變的。這也意味着返回類型只能是T。

public interface IIndex<out T>
{
      T this[int index] { get; }
      int Count { get; }
}

4.3 泛型接口的抗變



PS:對泛型結構瞭解還不深,希望大家能夠幫助我多瞭解瞭解,謝謝。



小結:

(1)泛型類似於一個模板。在把值類型轉換爲引用類型,和把引用類型轉換爲值類型時,需要進行裝箱和拆箱操作。

(2)代碼1:

namespace restudy5_1_2
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new ArrayList();
            list.Add(123);
            list.Add("aaa");
            list.Add("monb");

            foreach (var i in list)
            {
                Console.WriteLine(i);
            }

        }
    }
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章