[讀書筆記] 泛型程式設計特性

來源:互聯網
上載者:User

  在建立泛型類時,需要一些其他C#關鍵字。例如,不能把null賦值給泛型型別,此時可以使用default關鍵字。如果泛型型別不需要object類的功能,但需要調用泛型類上的某些特定方法,就可以定義約束。

  • 預設值
  • 約束
  • 繼承
  • 靜態成員

1.預設值

      現在給DocumentManager<T>類添加一個GetDocument()方法
      給類型T指定null,但是不能把null賦值給泛型型別
      泛型型別也可以執行個體化為實值型別,但是null只能用於參考型別,解決這個問題可以使用default關鍵字
      default關鍵字,將null賦予參考型別,將0賦予實值型別 

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Generics{    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;            }        }        // 預設值        // 現在給DocumentManager<T>類添加一個GetDocument()方法        // 給類型T指定null,但是不能把null賦值給泛型型別        // 泛型型別也可以執行個體化為實值型別,但是null只能用於參考型別,解決這個問題可以使用default關鍵字        // default關鍵字,將null賦予參考型別,將0賦予實值型別               public T GetDocument()        {            T doc = default(T);            lock (this)            {                doc = documentQueue.Dequeue();            }            return doc;        }    }    // 約束    // 如果泛型類需要調用泛型型別上的方法,就必須添加約束    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;        }    }    class Program    {        static void Main(string[] args)        {        }    }}

2.約束

如果泛型類需要調用泛型型別上的方法,就必須添加約束。

對於DocumentManager<T>,文檔的標題應在DisplayAllDocument()方法中顯示。

        // 要使用DocumentManger<T>來顯示文檔,可以將類型T強制轉換為IDocument介面        public void DisplayAllDocuments()        {            foreach (T doc in documentQueue)            {                Console.WriteLine(((IDocument)doc).Title);            }        }

如果類型T沒有執行IDocument介面,這個類型轉換就會產生一個運行異常。最好的辦法就是給DocumentManger<TDocument>類定義一個約束:TDocument類型必須執行IDocument介面。

public class DocumentManager<TDocument> where TDcoument : IDocument

 

這樣上面的語句就可以這樣寫了

        // 要使用DocumentManger<T>來顯示文檔,可以將類型T強制轉換為IDocument介面        public void DisplayAllDocuments()        {            foreach (TDocument doc in documentQueue)            {                Console.WriteLine(doc.Title);            }        }

 

下面是加了約束和帶有預設值特性的DocumentManager泛型類的完整代碼:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Generics{    public class DocumentManager<TDocument> where TDocument : IDocument    {        private readonly Queue<TDocument> documentQueue = new Queue<TDocument>();        public void AddDocument(TDocument doc)        {            lock (this)            {                documentQueue.Enqueue(doc);            }        }        public bool IsDocumentAvailable        {            get            {                return documentQueue.Count > 0;            }        }        // 預設值        // 現在給DocumentManager<T>類添加一個GetDocument()方法        // 給類型T指定null,但是不能把null賦值給泛型型別        // 泛型型別也可以執行個體化為實值型別,但是null只能用於參考型別,解決這個問題可以使用default關鍵字        // default關鍵字,將null賦予參考型別,將0賦予實值型別               public TDocument GetDocument()        {            TDocument doc = default(TDocument);            lock (this)            {                doc = documentQueue.Dequeue();            }            return doc;        }        public void DisplayAllDocuments()        {            foreach (TDocument doc in documentQueue)            {                Console.WriteLine(doc.Title);            }        }    }    // 約束    // 如果泛型類需要調用泛型型別上的方法,就必須添加約束    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;        }    }    class Program    {        static void Main(string[] args)        {            DocumentManager<Document> 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);            }            Console.ReadLine();        }    }}

 

出來的結果有點問題: 這個需要後面看下,怎麼回事。為什麼Document B的內容顯示不了

Title A
Title B
Sample A

上面的例子是一個關於介面約束的例子。泛型還有幾種約束類型

where T : struct 使用結構約束 類型T必須是實值型別

where T : calss 類約束指定, 類型T必須是參考型別

where T : IFoo 指定類型必須執行介面IFoo

where T : Foo 指定類型必須派生於基類Foo

where T : new() 這是一個建構函式約束,指定類型T必須有一個預設建構函式

where T : U 這個約束也可以指定,類型T1派生於泛型型別T2。該約束也稱為裸類型約束

 

3.繼承

泛型型別可以執行泛型介面,也可以派生於一個類。下面是幾種泛型介面的繼承

public class Base<T>{}public class Derived<T> : Base<T>{}

 

也可以這樣:

public class Base<T>{}public class Derived<T> : Base<string>{}

 

衍生類別可以是泛型類也可以是非泛型類。例如下面的計算機

public abstrac class Clac<T>{    public abstrac T Add(T x, T y);    public abstrac T Sub(T x, T y);}public class SimpleCalc : Calc<int>{     public override int Add(int x, int y)     {         return x + y;      }     public override int Sub(int x, int y)     {         return x - y;      }}

 

這樣的程式看起來,非常乾淨不錯O(∩_∩)O~

 

4.靜態成員

泛型類的靜態成員需要特別關注。泛型類的靜態成員只能在類的一個執行個體中共用。看下面的例子就知道了

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace GenericStatic{    class Program    {        public class StaticDemo<T>        {            public static int x;        }        static void Main(string[] args)        {            StaticDemo<string>.x = 4;            StaticDemo<int>.x = 5;            Console.WriteLine(StaticDemo<string>.x);            Console.ReadLine();        }    }}

 

結果輸出肯定很清楚了

4

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.