泛型是由2.0引进来的,有了泛型,就不再使用object类了。泛型相当于c++中的模板,泛型是C#语言的一个结构而且是CLR定义的。泛型的最大优点就是提高了性能,减少了值类型和引用类型的拆箱和装箱。
8.1 创建泛型类
创建泛型类和定义一般类类似,只是要使用泛型类型声明。下面给出例子:
泛型简单demo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace GenericDemo
{
//泛型
public class LinkedListNode<T>
{
public LinkedListNode(T value)
{
this.value = value;
}
private T value;
public T Value
{
get { return value; }
}
private LinkedListNode<T> next;
public LinkedListNode<T> Next
{
get { return next; }
internal set { next = value; }
}
private LinkedListNode<T> prev;
public LinkedListNode<T> Prev
{
get { return prev; }
internal set { prev = value; }
}
}
public class LinkedList<T> : IEnumerable<T>
{
private LinkedListNode<T> first;
public LinkedListNode<T> First
{
get { return first; }
}
private LinkedListNode<T> last;
public LinkedListNode<T> Last
{
get { return last; }
}
//添加
public LinkedListNode<T> AddLast(T node)
{
LinkedListNode<T> newNode = new LinkedListNode<T>(node);
if (first == null)
{
first = newNode;
last = first;
}
else
{
last.Next = newNode;
last = newNode;
}
return newNode;
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
LinkedListNode<T> current = first;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
#endregion
#region IEnumerable Members
//返回枚举值
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
class Program
{
static void Main(string[] args)
{
//所使用泛型
LinkedList<int> list2 = new LinkedList<int>();
list2.AddLast(3);
list2.AddLast(5);
list2.AddLast(7);
foreach (int i in list2)
{
Console.WriteLine(i);
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace GenericDemo
{
//泛型
public class LinkedListNode<T>
{
public LinkedListNode(T value)
{
this.value = value;
}
private T value;
public T Value
{
get { return value; }
}
private LinkedListNode<T> next;
public LinkedListNode<T> Next
{
get { return next; }
internal set { next = value; }
}
private LinkedListNode<T> prev;
public LinkedListNode<T> Prev
{
get { return prev; }
internal set { prev = value; }
}
}
public class LinkedList<T> : IEnumerable<T>
{
private LinkedListNode<T> first;
public LinkedListNode<T> First
{
get { return first; }
}
private LinkedListNode<T> last;
public LinkedListNode<T> Last
{
get { return last; }
}
//添加
public LinkedListNode<T> AddLast(T node)
{
LinkedListNode<T> newNode = new LinkedListNode<T>(node);
if (first == null)
{
first = newNode;
last = first;
}
else
{
last.Next = newNode;
last = newNode;
}
return newNode;
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
LinkedListNode<T> current = first;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
#endregion
#region IEnumerable Members
//返回枚举值
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
class Program
{
static void Main(string[] args)
{
//所使用泛型
LinkedList<int> list2 = new LinkedList<int>();
list2.AddLast(3);
list2.AddLast(5);
list2.AddLast(7);
foreach (int i in list2)
{
Console.WriteLine(i);
}
}
}
}
8.2 泛型类的特性
a.默认值
通过使用default关键字,能够将null赋予引用类型,将0赋予值类型
b.约束
如果泛型类调用泛型类型上的方法,就必须添加约束下面给出一个例子来讲解。
约束demo
//接口
public interface IDocument
{
string Title { get; set; }
string Content { get; set; }
}
//使用约束
public interface IDocumentManager<TDocument>
where TDocument : IDocument
{
void AddDocument(TDocument doc);
TDocument GetDocument();
bool IsDocumentAvailable { get; }
}
public class Document : IDocument
{
public Document()
{
}
public Document(string title, string content)
{
this.Title = title;
this.Content = content;
}
public string Title {get; set;}
public string Content {get; set;}
}
public class DocumentManager<TDocument> : IDocumentManager<TDocument>
where TDocument: Document
{
private readonly Queue<TDocument> documentQueue = new Queue<TDocument>();
public void AddDocument(TDocument doc)
{
lock (this)
{
documentQueue.Enqueue(doc);
}
}
public TDocument GetDocument()
{
TDocument doc = default(TDocument);
lock (this)
{
doc = documentQueue.Dequeue();
}
return doc;
}
public bool IsDocumentAvailable
{
get { return documentQueue.Count > 0; }
}
public void DisplayAllDocuments()
{
foreach (TDocument doc in documentQueue)
{
Console.WriteLine(doc.Title);
}
}
}
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);
}
dm.DisplayAllDocuments();
}
}
public interface IDocument
{
string Title { get; set; }
string Content { get; set; }
}
//使用约束
public interface IDocumentManager<TDocument>
where TDocument : IDocument
{
void AddDocument(TDocument doc);
TDocument GetDocument();
bool IsDocumentAvailable { get; }
}
public class Document : IDocument
{
public Document()
{
}
public Document(string title, string content)
{
this.Title = title;
this.Content = content;
}
public string Title {get; set;}
public string Content {get; set;}
}
public class DocumentManager<TDocument> : IDocumentManager<TDocument>
where TDocument: Document
{
private readonly Queue<TDocument> documentQueue = new Queue<TDocument>();
public void AddDocument(TDocument doc)
{
lock (this)
{
documentQueue.Enqueue(doc);
}
}
public TDocument GetDocument()
{
TDocument doc = default(TDocument);
lock (this)
{
doc = documentQueue.Dequeue();
}
return doc;
}
public bool IsDocumentAvailable
{
get { return documentQueue.Count > 0; }
}
public void DisplayAllDocuments()
{
foreach (TDocument doc in documentQueue)
{
Console.WriteLine(doc.Title);
}
}
}
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);
}
dm.DisplayAllDocuments();
}
}
说明:对于上面代码中的DocumentManager<T>,文档的标题应在DisplayAllDocuments方法显示。要是这个方法显示文档,可以将类型T强制转换为IDocument接口,来显示标题。如下代码:
public void DisplayAllDocuments()
{
foreach (T doc in documentQueue)
{
Console.WriteLine(((IDocument)doc).Title);
}
}
{
foreach (T doc in documentQueue)
{
Console.WriteLine(((IDocument)doc).Title);
}
}
当类型T没有执行IDocument接口,这个类型转换将会生成一个运行异常。如何解决这个问题呢,这个时候使用约束就可以了,就是给DocumentManager<TDocument>类定义一个约束:让TDocument类型必须执行IDocument接口,可以使用where子句指定了执行Idocument接口的要求。如下代码:
public class DocumentManager<TDocument> : IDocumentManager<TDocument>
where TDocument: Document
where TDocument: Document
这样就可以编写了,让类型T包含属性title啦,如下代码:
public void DisplayAllDocuments()
{
foreach (TDocument doc in documentQueue)
{
Console.WriteLine(doc.Title);
}
}
{
foreach (TDocument doc in documentQueue)
{
Console.WriteLine(doc.Title);
}
}
c.继承
泛型类型可以执行泛型接口,也可以派生于一个类。
下面给出一个例子来:
泛型继承demo
public abstract class Calc<T>
{
public abstract T Add(T x, T y);
public abstract 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;
}
}
{
public abstract T Add(T x, T y);
public abstract 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;
}
}
d.静态成员
泛型中的静态成员只能在类得一个实例化中共享,下面看一个例子
静态成员demo
小结:泛型内容比较多,只是讲了一些比较基本的内容。 public class StaticDemo<T>
{
public static int x;
}
StaticDemo<string>.x = 4;
StaticDemo<int>.x = 5;
Console.WriteLine(StaticDemo<string>.x);
{
public static int x;
}
StaticDemo<string>.x = 4;
StaticDemo<int>.x = 5;
Console.WriteLine(StaticDemo<string>.x);