前言
为什么要把反射和泛型放在一起讲呢,这里是处于个人对C#的一个很棒的观感,因为C#的反射是可以获取泛型里的元素的,而不像Java一个让我比较难受的地方就是Java的泛型实际编译的时候会擦除类型信息。那么问题来了,什么是泛型,什么又是反射呢?
泛型
请原谅我先介绍泛型,因为没有泛型基础直接介绍反射是不完整的,就比如说你辛辛苦苦拿到一个类的反射信息,等用的时候才发现结果这是一个泛型类,那还得解析这个类的泛型的信息,这时候就必须先有一个泛型的基础。那么什么是泛型呢,先看看百度百科给的定义:
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。
额,说实话哈,有一部分我没看懂他写的是啥。根据我的理解,泛型就是模板类里套的参数。就好比我们从网上找到一个好看的PPT模板,我们在写PPT的时候根据我们的主题套用这个模板,然后写出一个很好看的PPT,被老板表扬升职加薪。嗯,事实上用好了泛型也会升职加薪。
泛型说的笼统一些就是类型参数化的过程,我们之前介绍的List就是一个泛型类。泛型分泛型类/接口和泛型方法。泛型类和泛型接口可以看做是一种,因为它的泛型参数是用在整个结构体里面的(注意不是结构,struct);泛型方法又有参数泛型和返回值泛型两种。
声明一个泛型类/接口
publicclassTemplateT
{
privateTdata;
publicvoidSetTemplate(Ttemp)
{
data=temp;
}
publicTGetTemplate()
{
returndata;
}
}
上述示例是一个简单的泛型类,体现了泛型类的特点。在声明类的时候,声明一个泛型占位符
T
,在下面的属性、字段、方法的参数和方法的返回值都可以使用这个占位符,约定类型一致。
泛型的接口和泛型类是一致的,只不过接口没有方法的实现内容也就是方法体而已。
泛型类的使用
//继续上面的代码
Templateinttemp=newTemplateint();
temp.SetTemplate(10);
intten=temp.GetTemplate();
使用泛型类和普通类不同的地方就是,泛型类告诉编译器你要传递的类型。使用做标记,中间写类型,表示这是一个泛型为XXX的泛型类。通常与其他语言不同的地方是,C#的泛型支持所有类型,意思就是在没有额外声明的时候,可以使用任意类型作为泛型参数传递。
泛型方法
C#也可以声明一个方法为泛型方法,方法的泛型声明是声明在方法名的后面,参数列表的前方。
publicvoidTemplateMethodT(Targ);
publicTTemplateMethod1T();
publicTTemplateMethod2T(Targ);
上述三个都是合规的泛型方法声明。泛型可以是参数,也可以是返回值,还能既是返回值又是参数。
那么问题来了,多个泛型参数该怎么声明?
如下:
publicT2TemplateMothod3T1,T2(T1arg);
publicT3TemplateMothod4T1,T2,T3(T1arg,T2arg2);
在两个尖括号中间放入多个泛型,然后用逗号隔开,与参数列表和返回值的类型一一对应。
泛型方法的使用
TemplateMethod(10);//方式1
intit=TemplateMethod1int();//方式2
由于篇幅和时间的关系(主要是我写这篇的时候时间有点晚了。。)就不对之前所有的方法进行演示了。
这里简单介绍一下泛型方法的使用:
方式1隐藏了一个泛型参数,这是因为如果泛型是参数的话,c#会根据参数的类型自动解析对应的泛型类型是什么,方式1等同于TemplateMethodint(10);。方式2当泛型参数是返回值时,必须告知具体的泛型类型。
泛型约束和泛型标记
约束
在实际开发过程中,我们会对一些泛型类的泛型参数进行类型约束,那么泛型约束应该怎么写呢,看示例:
publicvoidDemoT(Targ)whereT:约束内容
publicvoidDemoT,P(Targ,Parg1)whereT:约束内容whereP:约束内容
如果对多个参数进行约束,就写多个where。
泛型的约束有一下几种:
class表示这是个引用类型new()表示必须有一个无参构造函数struct表示是个结构体具体的类名或接口名表示这个参数必须是这个类的子类或接口的实现类
泛型标记
在C#里有个很有意思的地方,那就是泛型标记。
泛型支持in/out作为占位符T的前置标记。那这两个标记是什么意义呢,in表示这个类型参数只能作为参数列表的类型进行传递,out表示这是一个返回值的类型,示例如下:
publicT2DemoinT1,outT2(T1t1);
类和方法的标记大同小易,基本上是一致的。