C#泛型类
一、泛型类的简介
所谓的泛型就是不知道具体的类型的一种通用表达。泛型和概念和C++中的模板,LabVIEW中的变体略有相似。用泛型定义的类具有多态的作用。
泛型的出现目的在于解决能应用在不同数据类型上的共有代码。
示例如下:
class Program
{
public class Static<T> //定义的泛型类
{
int pos;
T[] data =new T[100]; //定义泛型数组
public void Push(T obj) //入栈操作
{
data[pos++] = obj;
}
public T Pop(T obj) //出栈操作
{
return data[--pos];
}
}
static void Main(string[] args)
{
var stack = new Stack<int>();
//也可写成:Stack<int> stack=new Stack<int>();
stack.Push(5);
stack.Push(10);
int x = stack.Pop(); //x=5
int y = stack.Pop(); //y=10
Console.WriteLine("{0},{1}",x,y); //输出10,5
Console.ReadKey();
}
如上,泛型类的定义中,Static中的T就是就是一个占位符。他表示整个类中的所有涉及到的T是一种暂时不知道类型的占位符。在使用中指定T的类型即可。就像var stack=new Stack();一样,他会指定int为T的具体类型。
如上所示的:
Stack 称之为开放类型
Stack 称之为封闭类型
在运行时,所有的泛型类型的实例都被封闭了,也就是说所有T的占位符全部被填充了。
所以总结上面的代码,最终在运行时,Stack类最终会变成
public class 类名 //这里的类型为系统定义的默认名称。
{
int pos;
int[] data=new int[100];
public void Push(int obj)
{
data[pos++]=obj;
}
public int Pop()
{
return data[--pos];
}
}
二、泛型为什么会出现
上述我们可知,泛型的出现目的就是为了解决能针对不同类型的共用代码。如果仅仅是为了共用代码的话,其实还可以通过object类来进行操作。如下:
class Program
{
public class ObjectStack //定义的泛型类
{
int pos=0;
object[] data =new object[100]; //泛型数组
public void Push(object obj) //入栈操作
{
data[pos++] = obj;
}
public object Pop() //出栈操作
{
return data[--pos];
}
}
static void Main(string[] args)
{
ObjectStack stack = new ObjectStack();
//也可写成:Stack<int> stack = new Stack<int>();
stack.Push(5);
stack.Push(10);
int x = Convert.ToInt32(stack.Pop()); //x=5
int y = Convert.ToInt32(stack.Pop()); //y=10
Console.WriteLine("{0},{1}",x,y);
Console.ReadKey();
}
上述代码的结果与一种一样。
那么既然用Object也能实现同样的目的,为什么还要引出泛型类型呢。
我们知道,Object是个基类。操作中的10和5是个数值,想要将10和5转换成类的成员的话,一定会有装箱操作,反之需要拆箱操作。正因为装箱和拆箱的效率问题,才导致我们最好使用泛型而不是用Object类。
另外,在转换中无法进行检查,导致隐含风险。
例如:
stack.Push(“s”);编译不会出错,因为"s"也能装箱为Object
int i=(int)satck.Pop(); //运行出错,因为“s”拆箱后转换成int语法错误。
综上所述:
泛型是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。 延迟思想在程序架构设计的时候很受欢迎。例如:分布式缓存队列、EF的延迟加载等等。