博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编写高质量代码改善C#程序的157个建议——建议16:元素数量可变的情况下不应使用数组...
阅读量:5085 次
发布时间:2019-06-13

本文共 2756 字,大约阅读时间需要 9 分钟。

建议16:元素数量可变的情况下不应使用数组

在C#中,数组一旦被创建,长度就不能改变。如果我们需要一个动态且可变长度的集合,就应该使用ArrayList或List<T>来创建。 而数组本身,尤其是一维数组,在遇到要求高效率的算法时,则会专门被优化以提升其效率。一维数组也成为向量,其性能是最佳的,在IL中使用了专门的指令来 处理它们(如newarr、ldelem、ldelema、ldelen和stelem)。

 

从内存的使用角度来讲,数组在创建时被分配了一段固定长度的内存。如果数组的元素是值类型,则每个元素的长度等于相应的值类型的长度;如果数组的元素是引用类型,则每个元素的长度为该引用类型的IntPtr.Size(IntPtr:It's a class that wraps a pointer that is used when calling Windows API functions. The underlying pointer may be 32 bit or 64 bit, depending on the platform.)。数组的存储结构一旦被分配,就不能再变化。而ArrayList是链表结构,可以动态的增减内存空间,如果ArrayList存储的是值类型,则会为每个元素增加12字节的空间,其中4个字节拥有对象引用,8字节是元素装箱时引入的对象头。List<T>是ArrayList的泛型实现,它省去了装箱和拆箱带来的开销。

注意:

由于数组本身在内存上的特点,因此在使用数组的过程中还应该注意大对象的问题。所谓“大对象”,是指那些占内存超过85000字节的对象,它们被分配在大对象堆里。大对象的分配和回收和小对象都不太一样,尤其是回收,大对象在回收过程中会带来效率很低的问题。所以,不能对数组指定过大的长度,这会让数组成为一个大对象。

 

如果一定要动态改变数组的长度,一种方法是将数组转换为ArrayList或List<T>,如下面代码说是:

int[] iArr = { 0, 1, 2, 3, 4, 5, 6 };            ArrayList arrayListInt = new ArrayList(iArr);   //将数组转变为ArrayList            arrayListInt.Add(7);            List
listInt = iArr.ToList
(); //将数组转变为List
listInt.Add(7);

还有一种方法是数组的复制功能。数组继承自System.Array,抽象类System.Array提供了一些有用的实现方法。其中就包括Copy方法,它负责将一个数组的内容复制到另外一个数组中。无论哪种方法,改变数组长度就相当于重新创建了一个数组对象。

 

为了让数组看上去本身就具有动态改变长度的功能,可以创建一个名为Resize的扩展方法,代码如下所示:

public static class ClassForExtensions    {        public static Array ReSize(this Array array, int newSize)        {            Type t = array.GetType().GetElementType();            Array newArray = Array.CreateInstance(t, newSize);            Array.Copy(array, 0, newArray, 0, Math.Min(array.Length, newSize));            return newArray;        }    }

调用方法看起来如下:

int[] iArr = { 0, 1, 2, 3, 4, 5, 6 };iArr = (int[])iArr.ReSize(10);

下面对改变数组长度和改变Lisit<T>长度的耗时做一个比较,以便强调本建议的主题:在元素数量可变的情况下不应该使用数组。

private static void ResizeArray()        {            int[] iArr = { 0, 1, 2, 3, 4, 5, 6 };            Stopwatch watch = new Stopwatch();            watch.Start();            iArr = (int[])iArr.ReSize(10);            watch.Stop();            Console.WriteLine("ResizeArray: " + watch.Elapsed);        }        private static void ResizeList()        {            List
iArr = new List
(new int[] { 0, 1, 2, 3, 4, 5, 6 }); Stopwatch watch = new Stopwatch(); watch.Start(); iArr.Add(0); iArr.Add(0); iArr.Add(0); watch.Stop(); Console.WriteLine("ResizeList: " + watch.Elapsed); }

输出为:

ResizeArray:00:00:00.0004441

ResizeList:00:00:0:0000036

当然,严格意义上讲,List<T>不存在改变长度的说法,本建议只是为了比较,将iArr的长度变为10,同时还进行了赋值。即便这样,我们可以看到,在时间效率上ResizeList比ResizeArray要高100倍以上。

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

转载于:https://www.cnblogs.com/jesselzj/p/4728014.html

你可能感兴趣的文章
新作《ASP.NET MVC 5框架揭秘》正式出版
查看>>
IdentityServer4-用EF配置Client(一)
查看>>
WPF中实现多选ComboBox控件
查看>>
读构建之法第四章第十七章有感
查看>>
Windows Phone开发(4):框架和页 转:http://blog.csdn.net/tcjiaan/article/details/7263146
查看>>
Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)【转】
查看>>
python asyncio 异步实现mongodb数据转xls文件
查看>>
TestNG入门
查看>>
【ul开发攻略】HTML5/CSS3菜单代码 阴影+发光+圆角
查看>>
IOS-图片操作集合
查看>>
IO—》Properties类&序列化流与反序列化流
查看>>
测试计划
查看>>
Mysql与Oracle 的对比
查看>>
jquery实现限制textarea输入字数
查看>>
Codeforces 719B Anatoly and Cockroaches
查看>>
jenkins常用插件汇总
查看>>
c# 泛型+反射
查看>>
第九章 前后查找
查看>>
Python学习资料
查看>>
jQuery 自定义函数
查看>>