C#泛型-泛型类

为什么需要泛型:

CLR 2.0的一个新特性是泛型。在.CLR 1.0 中,要创建一个灵活的类或方法,但该类或方法在编译期间不知道使用什么类,就必须以 Object 类为基础。而 Object 类在编译期间没有类型安全性,因此必须进行强制类型转换。另外,给值类型使用Object类会有性能损失。

 

性能 

第一、泛型的一个主要优点是性能.避免装箱,拆箱

   例如:ArrayList方法Add(Value),value值只要继承object均可以添加进去,但是需要:装箱 ;foreach时需要拆箱

  (从值类型转换为引用类型称为装箱反之称拆箱)

 

第二、类型安全

  例如:List<T>中,泛型类型 T若 定义了允许使用的类型int,那么Add(value)方法中value只允许int值类型

 

第三、二进制代码重用(泛型类可以定义一次,用许多不同的类型实例化)

  例如:List<int> list = new List<int>(); list.Add(1); 

              List<string> stringList = new List<string>(); stringList.Add("string");

  泛型类型可以在一种语言中定义,在另一种.NET语言中使用。 

 

 

案例:

DocumentManager

/*
 * 说明:使用泛型文档管理器的示例 
 * 
 * 注意: 
 * default关键字根据上下文可以有多种含义。switch语句使用 default定义默认情况。在泛型中,根
 * 据泛型类型是引用类型还是值类型,default关键字用于将泛型类型初始化为 null或 0。 
 *
 * 创建:2012-04-26
 */
using System;
using System.Collections.Generic; 
using System.Text;
using System.Collections;

namespace DocumentManager
{
    //类约束指定,类型 T必须执行接口IDocument
    public class DocumentManager<T> where T :IDocument
    {

        private readonly Queue<T> documentQueue = new Queue<T>();
        /// <summary>
        /// AddDocument()方法将一个文档添加到
        /// 队列中。如果队列不为空,IsDocumentAvailable只读属性就返回 true
        /// </summary>
        /// <param name="doc"></param>
        public void AddDocument(T doc)
        {
            lock (this)
            {
                documentQueue.Enqueue(doc);
            }
        }
        /// <summary>
        /// 队列中有值返回True否则False
        /// </summary>
        public bool IsDocumentAvailable
        {
            get { return documentQueue.Count > 0; }
        }
        /// <summary>
        /// 给类型 T指定默认值 
        /// </summary>
        /// <returns></returns>
        public T GetDocument()
        {
            T doc = default(T); //泛型默认值:使用 default 关键字
            lock (this)
            {
                doc = documentQueue.Dequeue();
            }
            return doc;
        }
        /// <summary>
        /// 展示所有文档
        /// </summary>
        public void DisplayAllDocument()
        {
            foreach (T doc in documentQueue)
            {
                Console.WriteLine(((IDocument)doc).Title);
            } 
        }  
    }
}

Document

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DocumentManager
{
    public class Document : IDocument
    {
        public Document() 
        {

        }
        public string Title { get; set; }
        public string Content { get; set; }
        public Document(string title, string content)
        {
            this.Title = title;
            this.Content = content;
        }
    }
}

TDocument

namespace DocumentManager
{
    public class TDocument : IDocument
    {
        public TDocument() 
        {

        }
        public string Title { get; set; }
        public string Content { get; set; }
        public TDocument(string title, string content)
        {
            this.Title = title;
            this.Content = content;
        }
    }
}

 

/*
 * 如果泛型类需要调用泛型类型上的方法,就必须添加约束 
 * 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DocumentManager
{
    public interface IDocument
    {
        string Title { get; set; }
        string Content { get; set; }
    }
}

 

Program

 class Program
    {
        static void Main(string[] args)
        {
            //DocumentManager<TDocument> tm = new DocumentManager<TDocument>();
            //tm.AddDocument(new TDocument("Title TDocument","Content TDocument"));
            //tm.DisplayAllDocument();

            DocumentManager<Document> dm = new DocumentManager<Document>();
            dm.AddDocument(new Document("Title A", "Sample A")); 
            dm.DisplayAllDocument();

            dm.AddDocument(new Document("Title B", "Sample B"));
            dm.DisplayAllDocument();
            if (dm.IsDocumentAvailable)
            {
                Document d = dm.GetDocument();
                Console.WriteLine(d.Content);
            }
        }
    }

 

 

结果:建议先自己心算下……

 

 

 

 

(是不是和你的意愿不一致?那再好好看看代码)

 

 

 

 

 

 

 

注意:

 
default关键字根据上下文可以有多种含义。switch语句使用 default定义默认情况。在泛型中,根
据泛型类型是引用类型还是值类型,default关键字用于将泛型类型初始化为 null或 0。

 

如果泛型类需要调用泛型类型上的方法,就必须添加约束 。格式: where+约束类型

 

约    束  说    明 
where T : struct  使用结构约束,类型 T必须是值类型 
where T : class  类约束指定,类型 T必须是引用类型 
where T : IFoo  指定类型T必须执行接口 IFoo
where T : Foo  指定类型T必须派生于基类 Foo
where T : new()  这是一个构造函数约束,指定类型 T必须有一个默认构造函数 
where T : U 

这个约束也可以指定,类型 T1 派生于泛型类型 T2。该约束也称为裸类型约

在where子句中,只能定义基类、接口和默认构造函数。

 

 

静态成员 

泛型类的静态成员需要特别关注。泛型类的静态成员只能在类的一个实例中共享
             //泛型类的静态成员需要特别关注。泛型类的静态成员只能在类的一个实例中共享
            //由于对一个string类型和一个int类型使用了 StaticDemo<T>类,所以存在两组静态字段:
            StaticDemo<int>.x = 1;
            StaticDemo<string>.x = 11;
            StaticDemo<char>.x = 111;
            Console.WriteLine(StaticDemo<string>.x);
            Console.WriteLine(StaticDemo<int>.x);
    public class StaticDemo<T>
    {
        public static int x;
    }

 

 

 

 

 

 

 

                                                                                                                                                         引自《C#高级编程》

 

 

posted @ 2012-04-26 16:05  PEPE YU  阅读(901)  评论(0编辑  收藏  举报