您的位置:首页 > 编程语言 > C#

C#个人总结,第5章:泛型

2014-09-28 16:57 253 查看

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);

            }

        }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: