[读书笔记] 泛型编程特性

  在创建泛型类时,需要一些其他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

 

你可能感兴趣的:(读书笔记)