WhiteEngine-专注图形渲染与游戏引擎技术的网站

新浪微薄腾讯微薄

最新碎语:暂无碎语

您的位置:WhiteEngine-专注图形渲染与游戏引擎技术的网站 >C#与Lua> C# List Array ArrayList区别整理

C# List Array ArrayList区别整理

数组:

        数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单但是数组也存在一些不足的地方。比如在数组的两个数据间插入数据也是很麻烦的,还有我们在声明数组的时候,必须同时指明数组的长度,数组的长度过长,会造成内存浪费,数组和长度过短,会造成数据溢出的错误。这样如果在声明数组时我们并不清楚数组的长度,就变的很麻烦了。C#中最先提供了ArrayList对象来克服这些缺点。

ArrayList        

        ArrayList.Net Framework提供的用于数据存储和检索的专用类,它是命名空间System.Collections下的一部分。它的大小是按照其中存储的数据来动态扩充与收缩的。所以,我们在声明ArrayList对象时并不需要指定它的长度。ArrayList继承了IList接口,所以它可以很方便的进行数据的添加,插入和移除.ArrayList好像是解决了数组中所有的缺点,那么它应该就是完美的了,为什么在C#2.0后又会出现List呢?在list中,我们不仅插入了字符串"abc",而且又插入了数字123。这样在ArrayList中插入不同类型的数据是允许的。因为ArrayList会把所有插入其中的数据都当作为object类型来处理。这样,在我们使用ArrayList中的数据来处理问题的时候,很可能会报类型不匹配的错误,也就是说ArrayList不是类型安全的。既使我们保证在插入数据的时候都很小心,都有插入了同一类型的数据,但在使用的时候,我们也需要将它们转化为对应的原类型来处理。这就存在了装箱与拆箱的操作,会带来很大的性能损耗。

        正是因为ArrayList存在不安全类型与装箱拆箱的缺点,所以在C#2.0后出现了泛型的概念。而List类是ArrayList类的泛型等效类。它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。

        ArrayList如果你不给定初始大小,.net会自动分配个默认的大小,比如10。当这个ArrayList中存的值超过10个时,.net会把ArrayList的体积自动扩展为原来的1倍,即10*2,如果你只有11个值,那后面9个空间就浪费了。

.net为什么会想到*2呢?为啥不多一个元素ArrayList大小就+1呢?那是因为,ArrayList是存储在连续的内存空间里的。一开始体积为10,存在连续10块内存中。当你体积变为11时,由于此时ArrayList空间不够了,.net会把整个ArrayList复制到一个新的内存连续区域,把原来的区域给垃圾回收了。所以ArrayList里存的数据,永远是连续的内存空间。这也就是为什么当你存的数据数超过体积(比如10)时,它会自动*2。这是用空间换时间的做法,因为如果你每增加一个元素,他体积只加1的话,那势必每次都得整体内存搬迁。。这样很耗性能。所以它索性*2,可以保证在这次搬迁后,短时间内不会再搬迁了。

List泛型的好处:
        
通过允许指定泛型类或方法操作的特定类型,泛型功能将类型安全的任务从您转移给了编译器。不需要编写代码来检测数据类型是否正确,因为会在编译时强制使用正确的数据类型。减少了类型强制转换的需要和运行时错误的可能性。泛型提供了类型安全但没有增加多个实现的开销。

List内存分配:

        当采用默认构造函数List<int> value = new List<int>();实例化一个List<T>对象时,.Net Framework只是在内存中申请了一块内存来存放List<T>对象本身(不包含List当中的Items元素)。
当为List<T>对象添加第一个Item元素时,List<T>对象会申请能存储4Item元素的内存空间,然后将Item元素存放在申请的空间里。
List<T>对象有一个Capacity属性用来表示当前List<T>对象的容量(即当前用于存放Item的内存空间能存放的Item的个数),可以手动的设置它来设定List<T>的容量(Capacity的改变将会导致重新申请内存)。
List<T>对象的Item元素数量超过了Capacity的数量时,List<T>对象会重新申请一块大小是原来Capacity的两倍的内存空间,然后将当前所有Item元素以及待添加元素复制到新的内存空间中。

知道了内存分配的原则,接下来就得根据这些原则来采用最优的方法保证有限的内存空间能得到合理的运用。归纳起来主要有如下你点:
1.当实例化一个List<T>对象时,如果能预知其Item元素的大致个数,应该在实例化一个List<T>对象的时候设置其Capacity值为接近于Item元素个数的最小值。这样的话可以避免在像List<T>中添加元素的时候,不断的申请内存与元素的复制。
2.当由于不断的调用Remove方法而导致Item元素的个数远远小于Capacity,就会造成内存的浪费。此时可以调用TrimExcess方法释放多余的内存。


总结:

1.List Array ArrayList分配的内存空间都是连续的。

2.ArrayList有装箱和拆箱的所带来的性能损耗。

3.使用泛型List既可以避免装箱和拆箱又能动态的分配内存大小。

4.无论ArrayList还是List都需要注意内存的分配情况,如果知道存储大小,应该使用Capacity设置item元素个数。


---

转载请注明本文标题和链接:《C# List Array ArrayList区别整理

分享到:

发表评论

路人甲 表情
看不清楚?点图切换 Ctrl+Enter快速提交