学过c++的朋友一定对下面的代码很熟悉吧:
2 using namespace std;
3 template<class T> class array
4 {
5 public:
6 array(int size)
7 {
8 a=new t[size];
9 }
10 //more interface .
11 private:
12 T* a;
13 }
以前一直以为c#没有泛性编程这个东西(惭愧啊 ),这几天才了解到其实c#2.0已经加入了这个激动人心的功能.
晚是晚了点,但是这么好的东西还是必须学习的.
一.什么是泛形
微软给出的定义是 :"泛型可以让类、结构、接口、委托和方法按它们存储和操作的数据的类型进行参数化"
我对这句话的理解为:
我们可以让类、结构、接口、委托和方法的字段,参数或者局部变量的类型动态的定义,而不需要为每种类型都进行定义.
二.为什么使用泛型
正如前面所说的我们不必因为类、结构、接口、委托和方法的字段,参数或者局部变量的类型不同,而定义不同的版本.
如果没有泛型的话我没定义Stack类则必须这样定义:
{
int[] items;
int count;
public void Push(int item) {}
public int Pop() {}
}
{
string[] items;
int count;
public void Push(string item) {}
public string Pop() {}
}
我相信聪明的大家肯定不会这样做的,大家都知道.NET有个特殊的 object类,讲到这里我想大家已经猜到了我要干什么了吧。对,我要用Object对象来实现这个堆栈.
2 {
3 object[] items;
4int count;
5
6public void Push(object item) {}
7
8public object Pop() {}
9}
10
问题没有这么简单吧,大家先看下面的代码
Stack stack = new Stack();
stack.Push( 3 );
int i = ( int )stack.Pop();
// 安全问题
Stack stack = new Stack();
stack.Push( new Customer());
string s = ( string )stack.Pop();
同时,虽然上面的代码错误使用了 Stack 类,但是从技术角度讲该代码可以视作是正确的,编译器不会报告编译时错误。这个问题在该代码被执行之前不会暴露出来,但在执行该代码时会引发 InvalidCastException。
显然,如果能够指定元素类型,Stack 类将能够从中受益。三.创建泛型
泛型提供了一种新的创建类型的机制,使用泛型创建的类型将带有类型形参。下面的示例声明一个带有类型形参 T 的泛型 Stack 类。类型形参在 < 和 > 分隔符中指定并放置在类名后。Stack<T> 的实例的类型由创建时所指定的类型确定,该实例将存储该类型的数据而不进行数据类型转换。这有别于同 object 之间的相互转换。类型形参 T 只起占位符的作用,直到在使用时为其指定了实际类型。注意,这里的 T 用作内部项数组的元素类型、传递给 Push 方法的参数类型和 Pop 方法的返回类型:
2 {
3T[] items;
4int count;
5
6public void Push(T item) {}
7
8public T Pop() {}
9}
10
简单把:)
四.使用泛型
泛型的堆栈我们是定义好了,那么我们该怎么用他呢??定义都这么简单用起来肯定也不会难的
2stack.Push(3 );
3int x = stack.Pop();
在 Stack<int> 类型中,出现的每个 T 都被替换为类型实参 int。在创建 Stack<int> 的实例后,items 数组的本机存储是 int[] 而不是 object[]。无疑,这比非泛型的 Stack提供了更高的存储效率。同样,Stack<int> 的 Push 和 Pop 方法所操作的也是 int 类型的值。如果将其他类型的值推入堆栈则产生编译时错误。而且在检索值时也不再需要将它们显式强制转换为原始类型。
同时泛型提供了强类型机制, 意味着如果将一个 int 值推入 Customer 对象的堆栈将导致错误.这样就定义好了一个int 型的Stack实例.