.net集合类的研究--Array,ArrayList,List<T>
2011-07-21 10:32
549 查看
最近研究Nhibernate,看着样例代码一知半解,苦恼万分,发现中间又引用了一个Iesi.Collections,不禁要产生疑问--为什么要专门引用一个集合类程序集?这个程序集里的集合数组类与.net自带的有什么不一样?结果此问题一出就一发不可收拾,扪心自问冒出了一大堆的问题--.net有哪些集合类?array和ArrayList有什么区别?Hashtable与集合有什么不一样?....等等.这时才意识到,如果对.net本身提供的集合类不了解,根本不会明白引用Iesi.Collections的用意.由<<CLR via C#>>的书中所说:"所有的数组(如int[],FileStream[],object[])都隐式派生自System.Array,所有数组都隐式实现IEnumerable,ICollection,IList",所以先从Array开始研究,用Reflector工具找到Array源代码,发现除去一堆的静态方法如Sort,Find,BinarySearch以外,几乎就不剩什么东西了.其中比较重要的一点是Array仅仅用显示接口实现了一个私有IList.Add方法,这意味着:Array实例没有办法调用Add方法,一旦初始化以后,长度不可变.
ArrayList有Add方法,当Add方法发现内部的object[]容量已满时,便会调用一个方法自动扩充object[]容量,既然ArrayList的实质是操作object[],而Array长度不可变,那么如何扩充?其实说白了,就是通过调用EnsureCapacity方法再创建一个更长的object[]数组,然后把原数组复制到新的数组中.ArrayList的很多方法如Sort,Indexof,内部都是调用了Array的静态方法,如IndexOf方法:
.net2.0以后出现了泛型,目的是为了避免装箱拆箱操作造成的性能损失.ArrayList对应的泛型集合就是List<T>.由于泛型的出现,List<T>内部操作的不再是object[],而是T[],提供的很多方法如Sort,IndexOf等,同ArrayList类一样,内部也是调用Array的静态方法来操作数组.因为Array的局限性,List<T>的一些方法会用到循环,如Find方法:
其中Predicate<T>是一个委托,在.net内部定义,需要一个类型为T的参数,返回值为bool.知道这些可以避免我们把这些方法用在自己写的循环中,造成性能损失.
Array,ArrayList和List<T>在使用上如何选择呢?由于泛型可以避免装箱拆卸的性能损失,2.0以后的泛型集合基本上能淘汰以前的非泛型集合,所以ArrayList不做考虑,只比较Array和List<T>.标准答案:确定了Array大小的时候,选用Array,不确定大小时,使用List<T>.个人观点:如果数组是1维的,使用List<T>和Array之间的性能损失微乎其微,而List<T>可以带来更大的灵活性,因为很多时候想法和业务逻辑是多变的,建议多用List<T>.刚写完后,查了博客园,发现这个问题在园子里已经被说的很透彻了,给出链接重新理解List<T>.
int IList.Add(object value) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); }同样通过源代码可以看到ArrayList和Array的区别,ArrayList内置了一个Array变量 _items(代码中红色标出),也就是说:ArrayList是Array的一层封装,实际数据操作还是针对Array.
[Serializable, ComVisible(true), DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(ArrayListDebugView))] public class ArrayList : IList, ICollection, IEnumerable, ICloneable { // Fields private const int _defaultCapacity = 4; private object[] _items; private int _size; // Methods ........... }
ArrayList有Add方法,当Add方法发现内部的object[]容量已满时,便会调用一个方法自动扩充object[]容量,既然ArrayList的实质是操作object[],而Array长度不可变,那么如何扩充?其实说白了,就是通过调用EnsureCapacity方法再创建一个更长的object[]数组,然后把原数组复制到新的数组中.ArrayList的很多方法如Sort,Indexof,内部都是调用了Array的静态方法,如IndexOf方法:
public virtual int IndexOf(object value) { return Array.IndexOf(this._items, value, 0, this._size); }
.net2.0以后出现了泛型,目的是为了避免装箱拆箱操作造成的性能损失.ArrayList对应的泛型集合就是List<T>.由于泛型的出现,List<T>内部操作的不再是object[],而是T[],提供的很多方法如Sort,IndexOf等,同ArrayList类一样,内部也是调用Array的静态方法来操作数组.因为Array的局限性,List<T>的一些方法会用到循环,如Find方法:
public T Find(Predicate<T> match) { if (match == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } for (int i = 0; i < this._size; i++) { if (match(this._items[i])) { return this._items[i]; } } return default(T); }
其中Predicate<T>是一个委托,在.net内部定义,需要一个类型为T的参数,返回值为bool.知道这些可以避免我们把这些方法用在自己写的循环中,造成性能损失.
Array,ArrayList和List<T>在使用上如何选择呢?由于泛型可以避免装箱拆卸的性能损失,2.0以后的泛型集合基本上能淘汰以前的非泛型集合,所以ArrayList不做考虑,只比较Array和List<T>.标准答案:确定了Array大小的时候,选用Array,不确定大小时,使用List<T>.个人观点:如果数组是1维的,使用List<T>和Array之间的性能损失微乎其微,而List<T>可以带来更大的灵活性,因为很多时候想法和业务逻辑是多变的,建议多用List<T>.刚写完后,查了博客园,发现这个问题在园子里已经被说的很透彻了,给出链接重新理解List<T>.
相关文章推荐
- C# 数组集合 <一>基本概念(Array&ArrayList&List<T>&SortList&LinkList的实现Code)
- .net集合类的研究--Array,ArrayList,List<T>
- .net集合类的研究-哈希表(一)--Hashtable,Dictionary<TKey,TValue>
- C# 中的集合(Array/ArrayList/List<T>/HashTable/Dictionary)
- .net集合类的研究-哈希表(一)--Hashtable,Dictionary<TKey,TValue>
- .net集合类的研究--链表—ListDictionary,LinkedList<T>
- C# 中的集合(Array/ArrayList/List<T>/HashTable/Dictionary)
- C#使用集合组织数据(HashTable、ArrayList、List<T>,Dictionary<K,V>
- .Net集合类的研究-有序集合(一)-SortedList、SortedList<TKey,TValue>
- C# 中的集合(Array/ArrayList/List<T>/HashTable/Dictionary)
- List<T>,ArrayList,IEnumerable的区别
- java操作<Map转换List——>list集合重新排序—>List集合转换成JSON>
- Java基础<十一>--->集合之List、Set
- C#中泛型集合List<T>反序列化问题及解决方法
- C#中Array与ArrayList与泛型数组 list<>的区别
- C#泛型集合List<T>自带方法之排序
- <java API源码初体验>1---collection集合之ArrayList原理分析
- C# IEnumerable<T>、IEnumerator<T>、List<T>、ArrayList、[]数组各各的区别
- How to cast List<Object> to List<MyClass> Object集合转换成实体集合
- .Net集合类的研究-有序集合(二)-SortedDictionary<TKey,TValue>