泛型:泛型用来实现独立于被包含类型的功能。比如创建参数类型不同,但是功能相同的方法。
泛型的声明:
1、一般使用 <T> 来声明,T(可以用其他大写字母代替) 代表要被替换的类型,可以是值类型或引用类型;
2、<T> 放在类名,方法名(方法的参数列表之前),接口名后面,语句块之前;
3、可以给泛型定义约束,使用 where 关键字,如 public class A<T> where T:class;
4、多个泛型的声明,<T1,T2> 中间用逗号隔开。
下面给出 where 约束的相关表格:
注意:一个泛型可以给出多个约束,中间用逗号隔开,new()放在最后。多个泛型的约束为每个泛型使用 where,where间使用空格隔开(不必须)。
下面给出示例:
// 泛型类 A 有两个泛型:T,T1,他们分别是类约束和结构约束,表示T只能是引用类型,T1只能是值类型
public class A<T,T1>where T:class where T1:struct
{
}
// 泛型类 B 有两个约束:1、引用类型 2、带有默认构造函数
public class B<T>where T:class,new()
{
}
泛型的优点:
1、优化性能,减少装箱和拆箱带来的性能损耗;
2、类型安全,使用时指定了特定的类型,在该类型上进行操作是安全的;
3、最大限度的重用代码,针对不同类型的相同功能,使用泛型简单方便。
拓展:
1、装箱:将值类型转换成引用类型,也就是将值类型的数据复制到堆上,放到一个装箱的对象中,自动进行(如 int 装箱成 object)。
2、拆箱:将引用类型转换成值类型,需要强制类型转换,如果转换不正确,会报错。
下面给出示例说明:
// object 类型集合,可以将任意类型的数据放入集合中,所以操作时有很多类型,很容易出错(类型不安全)
ArrayList a = new ArrayList();
// 装箱:将值类型 int 转换成了引用了类型 object
a.Add(1);
a.Add("str");
// 拆箱:将引用类型转换成值类型
int b = (int)a[0] + 1;
// 这种转换会出错(编译时报错),因为 a[1] 是一个字符串
// int c = (int)a[1] + 2;
// 泛型集合,只能接受 int 类型 的数据,对他进行操作不会有装箱和拆箱,而且类型安全
List<int> d = new List<int>();