技术开发 频道

CLR系列:浅析泛型的本质

  【IT168 技术文档】泛型早在.net2.0就出来了,大家已经对它的使用很熟悉了,在工作中也大量的使用过它,但是大家对其工作原理,以及MS针对泛型对CLR做了那些工作是否了解呢。本文就是对泛型的本质进行讲解,希望能对大家有所帮助。

  1.引入泛型

  .Net2.0出来的时候,大家很轰动,其中.NET2.0做的一个很大的改变就是增加了泛型。在1.1的版本,大家还在使用一些如:ArrayList等集合。就算现在是.net3.5的时代,还是有很多程序员在继续使用1.1版本的集合,并没有采用范型集合,毕竟一个新技术的使用是要一段时间的,也许大家看了本文后会在适当的时候使用范型。

ArrayList arr = new ArrayList();
List
<int> arr1 = new List<int>();
for (int i = 1; i < 10; i++)
{
     arr.Add(i);
     arr1.Add(i);
}

  这是一个很基础的泛型应用,可能大家大部分使用泛型都是类似上面的方式。我们就从这个简单的代码讲起。表面上看好像1.1版本和2.0版本的集合使用上没什么其别,一样的方便。但是实质上MS在底层做了很多复杂的工作。我们看看它的IL代码:

IL_0012:  ldloc.0
IL_0013:  ldloc.
2
IL_0014:  box        [mscorlib]System.Int32
IL_0019:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::Add(
object)
IL_001e:  pop
IL_001f:  ldloc.
1
IL_0020:  ldloc.
2
IL_0021:  callvirt   instance
void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)

  在这里我们看看它第三行,熟悉IL的人都知道。这行box是在执行装箱操作。我们可以看看的Add方法原型:

ArrayList:
public virtual int Add(Object value) {
    
if (_size == _items.Length) EnsureCapacity(_size + 1);
    _items[_size]
= value;
    _version
++;
    
return _size++;
}
List:
public void Add(T item) {
    
if (_size == _items.Length) EnsureCapacity(_size + 1);
    _items[_size
++] = item;
    _version
++;
}

  我们可以看到ArrayList的Add方法的参数是object类型,我们都知道int --> object是要经过装箱操作,装箱操作又是个很费时间的事情,这就影响了性能。这里我们就引出泛型的第一个好处:性能的好处,避免了频繁的装箱拆箱操作。泛型的第二个好处:保证了类型的绝对安全,这点就不多讲了。上面的IL里多了一个类型:System.Collections.Generic.List`1这是.net CLR为泛型生成一个带“'”的类型,后面的数字表示<x,x>里参数x的个数。还有一个就是!0,这个是什么呢,请看下面的分析。

0
相关文章