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

        }
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值