随着集合的发展,我们使用集合的同时也发现集合的一些问题:由于类型的强制转换带来的类型安全问题,代码的复用率低,影响代码运行效率,比如:
所以为了避免上面的两个问题,.net2.0提出了泛型的概念。也就是泛型将类型参数的概念引入了 .net中,使用泛型可以最大限度得重用代码,保护类型的安全以及提高性能。
所谓泛型,就是通过参数化类型来实现在同一份代码上操作多种数据类型,它利用“参数化类型”将类型抽象化,使实现更为灵活地复用。
在泛型类或方法的定义中,类型参数是客户端代码在实例化泛型类型的变量时指定的特定类型的占位符。通常我们使用T作为类型参数占位符,但这并不是必须的,我们可以使用一些更有意义的描述性的名称作为类型占位符,如TInput 、TOutput等。
<span style="font-size:18px;"><span style="font-size:24px;"> public class List<TInput,TOutput></span></span>
但有些代码(如下),无法进行编译,为什么?因为我们没有对类型参数T进行类型的设置,这也就是我们通常所说的类型约束。
<span style="font-size:18px;"><span style="font-size:24px;">public class SortHelper<T> : IComparable{ public void BubbleSort(T[] array) { int length = array.Length; for (int i = 0; i <= length - 2; i++) { for (int j = length - 1; j >= 1; j--) { // 对两个元素进行交换 if (array[j] < array[j - 1]) { T temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } }</span></span>
所以,应用泛型约束的概念对上面的代码进行改善:
C#泛型要求对“所有泛型类型或泛型方法的类型参数”的任何假定,都要基于“显式的约束”,以维护C#所要求的类型安全。“显式约束”由where子句表达,而“显示约束”并非必须,如果没有指定的“显示约束”,泛型参数将只能访问System.object类型中的公有方法。
在定义泛型类型时可以对客户端代码在实例化类时用于类型参数的类型加以限制。约束使用where关键字来指定:
where T: struct 类型参数必须是值类型
where T: class 类型参数必须是引用类型
where T: new() 类型参数必须有一个 public 且无参数的构造函数
where T: <base classname> 类型参数必须继承至指定的基类(base class)
where T: <interface name> 类型参数必须是指定的接口或实现了指定接口的
关于泛型的博客先总结到这里,都是个人理解,欢迎各位拍砖。