泛型
来源:程序员人生 发布时间:2015-04-03 08:18:34 阅读次数:2936次
泛型概念:
泛型是公共语言运行时和编程语言提供的1种机制,它支持另外1种情势的代码重用,也就是算法重用.
泛型包括泛型类,泛型接口,泛型拜托,泛型方法,并不是只包括简单的泛型类.在C#中,其他例如,属性,索引器,事件,操作符方法,构造器本身不能有类型参数T.
T(类型参数),它的目的在于指明它操作的是1个未指定的数据类型,在源代码中能够使用数据类型的地方都可使用它.
为何要使用泛型
通过使用泛型,可以极大地提高代码的重用度,同时还可以取得强类型的支持,提升了利用程序的性能,避免了隐式的装箱、拆箱,和运行时的类型转换毛病。
提高代码复用
冒泡算法
不用泛型的情况下,如果是整数类型排序,下面代码中“?“就应为int类型,但如果这时候候我们有需要给byte类型排序,就要复制1遍代码,然后把int改成byte。这明显不能体现代码的复用。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>public class SortHelper {
public void BubbleSort(?[] 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]) {
temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
</strong></span>
做网站为了提高代码复用,我们通常使用模板它的具体做法是:每次生成静态页面时,先加载模板,模板中含有1些用特殊字符标记的占位符,然后从数据库读取数据,使用读出的数据将模板中的占位符替换掉。
将上面的方法视为1个模板,将方法所操作的类型视为1个占位符,由因而1个占位符,因此可以代表任何的类型,这和静态页面生成时模板的占位符可以用来代表来自数据库中的任何数据道理是1样的。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>public class SortHelper<T> {
public void BubbleSort(T[] array){
// 冒泡排序方法实现体
}
}
</strong></span>
在类型名称的后面加了1个尖括号,使用这个尖括号来传递占位符,也就是类型参数。
接下来,看1下如何使用泛型。
当需要为1个int类型的数组排序时:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>SortHelper<int> sorter = new SortHelper<int>();
int[] array = { 8, 1, 4, 7, 3 };
sorter.BubbleSort(array);
</strong></span>
当需要为1个byte类型的数组排序时:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>SortHelper<byte> sorter = new SortHelper<byte>();
byte [] array = { 8, 1, 4, 7, 3 };
sorter.BubbleSort(array);
</strong></span>
性能对照
拆装箱
1. 装箱在值类型向援用类型转换时产生
2. 拆箱在援用类型向值类型转换时产生
代码演示
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
const int ListSize = 500000;
static void Main(string[] args)
{
UseArrayList();
UseGenericList();
Console.ReadKey();
}
private static void UseArrayList()
{
ArrayList list = new ArrayList();
long startTicks = DateTime.Now.Ticks;
for (int i = 0; i < ListSize; i++)
{
list.Add(i);//i为int类型,list为援用类型, 存在1个装箱操作
}
for (int i = 0; i < ListSize; i++)
{
int value = (int)list[i];//list[i]为援用类型,value为int类型。 进行1个拆箱操作
}
long endTicks = DateTime.Now.Ticks;
Console.WriteLine("使用ArrayList,耗时:{0} ticks", endTicks - startTicks);
}
private static void UseGenericList()
{
List<int> list = new List<int>();
long startTicks = DateTime.Now.Ticks;
for (int i = 0; i < ListSize; i++)
{
list.Add(i);
}
for (int i = 0; i < ListSize; i++)
{
int value = list[i];
}
long endTicks = DateTime.Now.Ticks;
Console.WriteLine("使用List<int>,耗时:{0} ticks", endTicks - startTicks);
}
}
}
</strong></span>
运行效果
类型安全
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>ArrayList list = new ArrayList();
int i = 100;
list.Add(i);
string value = (string)list[0];
</strong></span>
有些经验的同学就能够看出这段代码有问题,由于类型不匹配,添加到ArrayList中的是1
个int类型,而获得时却想将它转换为string类。但是编译器不能辨认,不论是int也好,string也好,它们都是Object类型。在编写代码时,编译器提供给开发者的最大帮助之1就是可以检查出毛病,也就是常称的编译时毛病(Compile time error)。当使用ArrayList时,对上面的问题,编译器无能为力,由于它认为其是合法的,编译可以顺利通过。这类毛病有时候隐藏在程序中很难发现,最糟的情况是产品已交付用户,而当用户在使用时不巧履行到这段代码,便会抛出1个异常,这时候的毛病,称为运行时毛病(Runtime
error)。
通过使用泛型集合,这类情况将不复存在,当试图进行类似上面的转换时,根本没法通
过编译,这样有助于尽早发现问题:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>List<int> list = new List<int>();
int i = 100;
list.Add(i);
string value = (string)list[0]; // 编译毛病
</strong></span>
通过以上这些对照,可以看出泛型给我们编程提供了很大的方便,固然这些只是我查到的1些资料加上自己的整理和实践,如有不足的地方请大家批评指正。
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠