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


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

  • 相关阅读:
    安全测试基础知识
    Python思维导图(一)—— 基础
    Java 高级点的东西
    安全测试通用用例
    测试基础篇(一)—— 面试终极常见
    测试基础篇(二)—— 面试挺常见
    差分约束基本讲解
    0x42 数据结构进阶树状数组
    Codeforce Problem 711A Bus to Udayland (正则表达式)
    POJ 1456 Supermarket【贪心 + 并查集】
  • 原文地址:https://www.cnblogs.com/herbert/p/1742925.html
Copyright © 2020-2023  润新知