-
如何写出高质量的代码之数组优化
如何写出高质量有代码,首先,要看我们的目的及高质量代码的标准,一直以来,都认为高质量的代码就是体积小、速度快;不错,这确实是高质量代码所应具备的特征,但这不是全部,除此之外,还要考虑到CPU时钟占用及内存等因素。这里先简单说一下对集合的使用,在C#中的集合主要是数组和其它一些集合类;对这些集合类的使用是很有讲究的。
第一点,元素可变的情况下不要使用数组
在C#教程中,数组被创建后,长度是不能改变的。如需一个动态且可变长度的集合,就应该使用ArrayList或List<T>。而数组本身,尤其是一维数组,在遇到要求高效率的算法时,则会专门被优化以提升其效率。一维数组也称为向量,其性能是最佳的,在IL中使用了专门的指令来处理它们。
从内存使用的角度来讲,数组具有以下特点:
1、数组在创建时被分配了一段固定长度的内存。
2、如果数组元素是值类型,则每个元素的长度等于相应的值类型的长度
3、如果数组的元素是引用类型,则每个元素的长度为该引用类型的IntPtr.Size。
4、数组的存储结构一旦被分配,就不能再变化。
而ArryaList是这样的:
1、ArrayList是链表结构,可以动态增减内存空间。
2、如果ArrayList存储的是值类型,则会为每个元素增加12字节的空间,其中4字节用于对象引用,8字节是元素装箱时引入的对象头。
而List<T>是ArrayList的泛型实现,它省去了拆箱和装箱带来的开销。
如果一定要动态改变数组的长度,一种方法是将数组转换为ArrayList或List<T>,如下面的代码所示:
还有一种方法是用数组的复制功能。数组继承自System.Array,抽象类System.Array提供了一些有用的实现方法,其中就包含了Copy方法,它负责将一个数组的内容复制到另外一个数组中。无论是哪种方法,改变数组长度就相当于重新创建了一个数组对象。
为了让数组看上去本身就具有动态改变长度的功能,还可以创建一个名为ReSize的扩展方法。
调用方式如下:
Main函数中主要是调用,自己定义的两个方法,第一个是重新设置数组的长度,第二个是设置List<T>的长度,通过运行时间进行测量:
严格意义上讲,List<T>不存在改变长度的说法,此处主要是来进行对比一下,对List<T>设置长度,并且进行赋值,即便是这样,在时间效率上ResizeList比ResizeArray要高很多很多。
第一点,元素可变的情况下不要使用数组
在C#教程中,数组被创建后,长度是不能改变的。如需一个动态且可变长度的集合,就应该使用ArrayList或List<T>。而数组本身,尤其是一维数组,在遇到要求高效率的算法时,则会专门被优化以提升其效率。一维数组也称为向量,其性能是最佳的,在IL中使用了专门的指令来处理它们。
从内存使用的角度来讲,数组具有以下特点:
1、数组在创建时被分配了一段固定长度的内存。
2、如果数组元素是值类型,则每个元素的长度等于相应的值类型的长度
3、如果数组的元素是引用类型,则每个元素的长度为该引用类型的IntPtr.Size。
4、数组的存储结构一旦被分配,就不能再变化。
而ArryaList是这样的:
1、ArrayList是链表结构,可以动态增减内存空间。
2、如果ArrayList存储的是值类型,则会为每个元素增加12字节的空间,其中4字节用于对象引用,8字节是元素装箱时引入的对象头。
而List<T>是ArrayList的泛型实现,它省去了拆箱和装箱带来的开销。
如果一定要动态改变数组的长度,一种方法是将数组转换为ArrayList或List<T>,如下面的代码所示:
///定义一个一维数组
int[] iArr = { 0,1,3,4,6,7,9};
///将数组转换为ArrayList
ArrayList arrayListInt = ArrayList.Adapter(iArr);
arrayListInt.Add(11);
///将数组转换为List<T>
List<int> listInt = iArr.ToList<int>();
listInt.Add(11);
还有一种方法是用数组的复制功能。数组继承自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;
}
}
调用方式如下:
static void Main(string[] args)
{
int[] iArr = { 0,1,3,4,6,7,9};
iArr = (int[])ClassForExtensions.ReSize(iArr, 20);
Console.ReadLine();
}下面我们来对比一下性能,先来看代码:
class Program
{
static void Main(string[] args)
{
ResizeArray();
ResizeList();
Console.ReadLine();
}
public static void ResizeArray()
{
int[] iArr = {0,1,3,4,6,8 };
Stopwatch watch = new Stopwatch();
watch.Start();///用于测量时间间隔
iArr = (int[])iArr.ReSize(10);
watch.Stop();///
Console.WriteLine("ResizeArray:{0}", watch.Elapsed);
}
public static void ResizeList()
{
List<int> iArr = new List<int>(new int[] { 0, 1, 3, 4, 6, 8, 9 });
Stopwatch watch = new Stopwatch();
watch.Start();
iArr.Add(0);
iArr.Add(0);
iArr.Add(0);
watch.Stop();
Console.WriteLine("ResizeList:{0}", watch.Elapsed);
}
}
Main函数中主要是调用,自己定义的两个方法,第一个是重新设置数组的长度,第二个是设置List<T>的长度,通过运行时间进行测量:
严格意义上讲,List<T>不存在改变长度的说法,此处主要是来进行对比一下,对List<T>设置长度,并且进行赋值,即便是这样,在时间效率上ResizeList比ResizeArray要高很多很多。
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式