C#通过泛型避免进行强制类型转换,增强类型安全,减少装箱量,并让程序员更轻松地创建常规的类和方法。泛型类和方法接受类型参数,它们指定了要操作的对象的类型。C#是在尖括号中提供类型参数来指定泛型类,如下:
class Queue<T>
{
.....................
}
T就是类型参数,它作为占位符使用,会在编译时被真正的类型取代。写代码实例化泛型Queue时,需指定用于取代T的类型。在类中定义字段和方法时,可用同样的占位符指定这些项的类型,如下:
class Queue
{
private const int DEFAULTQUEUESIZE = 100;
private T[] data; //数组是“T”类型,“T”称为类型参数
private int head = 0;tail = 0;
private int numElements = 0;
public Queue ()
{
this.data = new T[DEFAULTQUEUESIZE];//“T”作为数据类型
}
public Queue(int size)
{
if(size > 0)
{
this.data = new T[size];
}
else
{
throw new ArgumentOutOfRangeException("XXXXXX");
}
}
public void Enqueue(T item)//"T"作为方法参数类型
{
if(this. numElements == this.data.Length)
{
throw new Exception("Queue full");
}
this.data[this.head] = item;
this.head++;
this.head %= this.data.Length;
this. numElements++;
}
public T Dequeue() //"T"作为返回类型
{
if(this. numElements == 0)
{
throw new Exception("Queue empty");
}
T queueItem = this.data[this.tail];//数组中的数据是“T”类型
this.tail++;
this.tail %= this.data.Length;
this. numElements--;
return queueItem ;
}
}
Queue intQueue = new Queue();
Queue horseQueue = new Queue();
intQueue.Enqueue(99);
int myInt = intQueue.Dequeue(); //不需要转换
可以想象泛型类定义了一个模板,编译器根据需要用该模板来生成新的、有具体类型的类。泛型类的具体类型版本(例如Queue , Queue等)称为已构造类型。它们应被视为不同的类型。
泛型和约束
有时要确保泛型类使用的类型参数是提供了特定方法的类型。例如,假定要定义一个PrintableCollection类,就可能想确保该类存储的所有对象都提供了Print方法。这时,可以用约束来规定该条件。
约束限制泛型类的类型参数实现了一组特定的接口因而提供了接口定义的方法。
public class PrintableCollection where T:IPrintable
创建泛型类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BinaryTree
{
public class Tree where TItem : IComparable
{
public TItem NodeData { get; set; }
public Tree LeftTree { get; set; }
public Tree RightTree { get; set; }
public Tree(TItem nodeValue)
{
this.NodeData = nodeValue;
this.LeftTree = null;
this.RightTree = null;
}
public void Insert(TItem newItem)
{
TItem currentNodeValue = this.NodeData;
if (currentNodeValue.CompareTo(newItem) > 0)
{
if (this.LeftTree == null)
{
this.LeftTree = new Tree(newItem);
}
else {
this.LeftTree.Insert(newItem);
}
}
else
{
if (this.RightTree == null)
{
this.RightTree = new Tree(newItem);
}
else
{
this.RightTree.Insert(newItem);
}
}
}
public string WalkTree()
{
string result = "";
if (this.LeftTree != null)
{
result = this.LeftTree.WalkTree();
}
result += String.Format(" {0} ",this.NodeData.ToString());
if (this.RightTree != null)
{
result += this.RightTree.WalkTree();
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BinaryTree;
namespace BinaryTreeTest
{
class Program
{
static void Main(string[] args)
{
Tree tree1 = new Tree(10);
tree1.Insert(5);
tree1.Insert(11);
tree1.Insert(5);
tree1.Insert(-12);
tree1.Insert(15);
tree1.Insert(0);
tree1.Insert(14);
tree1.Insert(-8);
tree1.Insert(10);
tree1.Insert(8);
tree1.Insert(8);
string sortedData = tree1.WalkTree();
Console.WriteLine("Sorted data is {0}",sortedData);
}
}
}
创建泛型方法
除了定义泛型类,还可以创建泛型方法。泛型方法允许采取和定义泛型类时相似的方式,同类型参数来指定参数和返回类型。
static void Swap(ref T first,ref T second)
{
T temp = first;
first = second;
second = temp;
}
调用这个方法时,必须为类型参数指定具体类型。下例展示了如何使用Swap方法来交换两个int和string:
int a = 1,b = 2;
Swap(ref a,ref b);
.......
string s1 = "Hello",s2 = "World";
Swap(ref s1,ref s2);