Welcome

首页 / 软件开发 / .NET编程技术 / .NET之我见系列 - 类型系统(下)

.NET之我见系列 - 类型系统(下)2012-02-11 博客园 刑天1,泛型

泛型在.NET中的重要价值已经无需用过多的语言来描述了。从.NET2.0提出泛型开始,这个东西已经被开发人员广为称道,颇有相见恨晚之意。可以想象得到,.NET在设计之初就想实现这种特性。微软把这一希望寄托在了System.Object上,但事后证明,后者所带来的性能开销是开发人员所无法接受的。因此纷纷弃用这一鸡肋。为了解决这一问题,在.NET2.0上,微软全力攻关,终于搞出了一个完美的解决方案,就是泛型。实际上,泛型是一种虚拟意义上的“泛型”,它的原理也很容易理解,就是在第一次编译时,使用一个占位符代替原来应使用类型的位置,当第二此编译时再用代码中指定的类型替换这个占位符。记得以前大学里上课时,经常有的寝室只派一个人来抢座位,把书或包放在空位置上,就表示这个位置已经有人,其他人不能再坐。等到上课前一分钟,这些人才睡眼惺惺地跑来抢现成的座位。大概想出泛型的这位老大也是受了大学里的启发(纯属猜测)。

这一过程用代码这样表示:

源程序中的代码:

class Human<T>
{
public void Say(T word)
{
Console.WriteLine(word.ToString());
}
}
这个泛型类表示了一个人类的类别,在类名Human后用<T>表示泛型的引入,其中T就是一个占位符,在此处,它可以表示任何的类型。而在Say方法中,T作为参数的类型,从而用于接收不同类型的值。

当第一编译结束后,以上程序的IL代码变成如下所示:

图中我们可以看到,无论是在Human类的后面和Say方法的参数中,都使用T来作为类型标识,当然T只是安装微软的规范,这里你完全可以用另一个字符或单词来表示,效果是同样的。但此时,类和方法还并不清楚自己是什么类型。直到调用该类的Main方法中出现下面的代码:

此时,通过智能感知提示,我们已经很清楚的看到,Say方法后的参数类型被指定为string型。表明泛型类在初始化时,指明了类型为string,并用string替换了占位符T。实际上这一转换发生在二次编译之时,也就是JIT编译时。由此我们可以得知,.NET的泛型是一种虚拟意义的泛型,只是利用了一个占位符为中介,让程序达到了泛型的效果。这也是一种较完美的解决方案。

顺便提一下,泛型的实现原理在王涛先生的《你必须知道的.NET》一书中第10章里讲得很清楚了,对这一概念仍不大清楚的朋友还可以去好好学习一下。