第十七章 泛型
1.泛型
封装的数据不指定特定类型,而在声明或实例化期间指定类型,以最大限度的重用代码、保护类型安全。
class Queue
{
private const int DEFAULTQUEUESIZE = 100;
private int head=0, tail=0;
private int elementCount = 0;
private int[] queue;
public Queue()
{
this.queue = new int[DEFAULTQUEUESIZE];
}
public void Enqueue(int item)
{
if(elementCount == this.queue.Length)
{
throw new Exception("Queue full");
}
this.queue[head] = item;
head++;
head %= this.queue.Length;
elementCount++;
}
public int Dequeue()
{
if(elementCount == 0)
{
throw new Exception("Queue empty");
}
int item = this.queue[tail];
tail++;
tail %= this.queue.Length;
elementCount--;
return item;
}
}
public static void Main(string [] args)
{
Queue queue = new Queue();
queue.Enqueue(90);
queue.Enqueue(10);
queue.Enqueue(20);
Console.WriteLine($"{queue.Dequeue()}");
Console.WriteLine($"{queue.Dequeue()}");
Console.WriteLine($"{queue.Dequeue()}");
// 输出:
// 90
// 10
// 20
}

a, head, tail相当于游标。向队列里添加一个元素,head游标向前移动一个格子;向队列里删除一个元素,tail游标向前移动一个格子。
b, head, tail游标都在向前移动,队列有 “先进先出,后进后出” 的特点。
c, Queue类仅支持int类型,string、long、float、自定义类型或其它类型却无法使用。使用泛型技术,设计类时不指定元素的具体类型,而使用泛型类型 T。
2.使用泛型
// 设计时,队列元素类型使用泛型类型 T
class GenericQueue<T>
{
private const int DEFAULTQUEUESIZE = 100;
private int head = 0, tail = 0;
private int elementCount = 0;
private T[] queue;
public GenericQueue()
{
this.queue = new T[DEFAULTQUEUESIZE];
}
public void Enqueue(T item)
{
if (elementCount == this.queue.Length)
{
throw new Exception("Queue full");
}
this.queue[head] = item;
head++;
head %= this.queue.Length;
elementCount++;
}
public T Dequeue()
{
if (elementCount == 0)
{
throw new Exception("Queue empty");
}
T item = this.queue[tail];
tail++;
tail %= this.queue.Length;
elementCount--;
return item;
}
}
class Pizza
{
private string _type;
public string Type{ get => this._type;}
public Pizza(string type)
{
this._type = type;
}
}
public static void Main(string [] args)
{
// 声明时,指定队列元素类型
GenericQueue<string> stringQueue = new GenericQueue<string>();
stringQueue.Enqueue("草莓蛋糕");
stringQueue.Enqueue("蛋挞");
stringQueue.Enqueue("热柠檬红茶");
GenericQueue<long> longQueue = new GenericQueue<long>();
longQueue.Enqueue(998);
longQueue.Enqueue(1024);
longQueue.Enqueue(520);
// 自定义Pizza队列
GenericQueue<Pizza> pizzaQueue = new GenericQueue<Pizza>();
pizzaQueue.Enqueue(new Pizza("海鲜披萨"));
pizzaQueue.Enqueue(new Pizza("培根牛肉披萨"));
pizzaQueue.Enqueue(new Pizza("什锦水果披萨"));
}
用指定类型替换泛型参数类型T,不是简单的文本替换机制。相反,编译器会执行全面的语义替换。
GenericQueue<string> stringQueue = new GenericQueue<string>(); // string队列
GenericQueue<Pizza> pizzaQueue= new GenericQueue<Pizza>(); // 自定义Pizza队列
// string队列的方法:
public void Enqueue(string item);
public string Dequeue();
// Pizza队列的方法:
public void Enqueue(Pizza item);
public Pizza Dequeue();
每次为泛型类指定类型参数时,编译器会生成一个全新的类,它“恰好”有泛型类定义的功能。 这意味着GenericQueue<string>和GenericQueue<Pizza>是全然不同的两个类型,只是“恰好”具有相同的行为。泛型类的具体类型版本称为已构造类型(constructed type)。

浙公网安备 33010602011771号