C#中数组Array,ArrayList,泛型List详细对比
在c#中数组array,arraylist,泛型list都能够存储一组对象,但是在开发中根本不知道用哪个性能最高,下面我们慢慢分析分析。
一、数组array
数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。
array 类是 c# 中所有数组的基类,它是在 system 命名空间中定义。
数组在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也非常简单。
array数组具体用法:
using system; namespace webapp { class program { static void main(string[] args) { //system.array //1、数组[] 特定类型、固定长度 string[] str1 = new string[3]; str1[0] = "a"; str1[1] = "b"; str1[2] = "c"; console.writeline(str1[2]); string[] str2 = new string[] { "a", "b", "c" }; console.writeline(str2[0]); string[] str3 = { "a", "b", "c" }; console.writeline(str3[0]); //2、二维数组 //int[,] intarray=new int[2,3]{{1,11,111},{2,22,222}}; int[,] intarray = new int[2, 3]; intarray[0, 0] = 1; intarray[0, 1] = 11; intarray[0, 2] = 111; intarray[1, 0] = 2; intarray[1, 1] = 22; intarray[1, 2] = 222; console.writeline("{0},{1},{2}", intarray[0, 0], intarray[0, 1], intarray[0, 2]); console.writeline("{0},{1},{2}", intarray[1, 0], intarray[1, 1], intarray[1, 2]); //3、多维数组 int[, ,] intarray1 = new int[,,] { {{1, 1}, {11, 11}, {111, 111}}, {{2, 2}, {22, 22}, {222, 222}}, {{3, 3}, {33, 33}, {333, 333}} }; console.writeline("{0},{1},{2},{3},{4},{5}", intarray1[0, 0, 0], intarray1[0, 0, 1], intarray1[0, 1, 0], intarray1[0, 1, 1], intarray1[0, 2, 0], intarray1[0, 2, 1]); console.writeline("{0},{1},{2},{3},{4},{5}", intarray1[1, 0, 0], intarray1[1, 0, 1], intarray1[1, 1, 0], intarray1[1, 1, 1], intarray1[1, 2, 0], intarray1[1, 2, 1]); console.writeline("{0},{1},{2},{3},{4},{5}", intarray1[2, 0, 0], intarray1[2, 0, 1], intarray1[2, 1, 0], intarray1[2, 1, 1], intarray1[2, 2, 0], intarray1[2, 2, 1]); //4、交错数组即数组的数组 int[][] intarray2 = new int[4][]; intarray2[0] = new int[] { 1 }; intarray2[1] = new int[] { 2, 22 }; intarray2[2] = new int[] { 3, 33, 333 }; intarray2[3] = new int[] { 4, 44, 444,4444 }; for (int i = 0; i < intarray2.length; i++) { for (int j = 0; j < intarray2[i].length; j++) { console.writeline("{0}", intarray2[i][j]); } } console.readkey(); } } }
数组虽然存储检索数据很快,但是也有一些缺点:
1、在声明数组的时候必须指定数组的长度,如果不清楚数组的长度,就会变得很麻烦。
2、数组的长度太长,会造成内存浪费;太短会造成数据溢出的错误。
3、在数组的两个数据间插入数据是很麻烦的
更多参考微软官方文档:array 类 (system)
二、arraylist
既然数组有很多缺点,c#就提供了arraylist对象来克服这些缺点。
arraylist是在命名空间system.collections下,在使用该类时必须进行引用,同时继承了ilist接口,提供了数据存储和检索。
arraylist对象的大小是按照其中存储的数据来动态扩充与收缩的。因此在声明arraylist对象时并不需要指定它的长度。
arraylist 的默认初始容量为 0。随着元素添加到 arraylist 中,容量会根据需要通过重新分配自动增加。可通过调用 trimtosize 或通过显式设置 capacity 属性减少容量。
using system; using system.collections; public class samplesarraylist { public static void main() { arraylist myal = new arraylist(); myal.add("hello"); myal.add("world"); myal.add("!"); console.writeline( "myal" ); console.writeline( " count: {0}", myal.count ); console.writeline( " capacity: {0}", myal.capacity ); console.write( " values:" ); printvalues( myal ); } public static void printvalues( ienumerable mylist ) { foreach ( object obj in mylist ) console.write( " {0}", obj ); console.writeline(); console.readkey(); } }
运行结果:
arraylist解决了数组中所有的缺点,但是在存储或检索值类型时通常发生装箱和取消装箱操作,带来很大的性能耗损。尤其是装箱操作,例如:
arraylist list = new arraylist(); //add list.add("joye.net"); list.add(27); //update list[2] = 28; //delete list.removeat(0); //insert list.insert(0, "joye.net1");
在list中,先插入了字符串joye.net,而且插入了int类型27。这样在arraylist中插入不同类型的数据是允许的。因为arraylist会把所有插入其中的数据当作为object类型来处理,在使用arraylist处理数据时,很可能会报类型不匹配的错误,也就是arraylist不是类型安全的。
更多参考微软官方arraylist文档:arraylist 类 (system.collections)
三、泛型list<t>
由于arraylist存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念。
list 类是 arraylist 类的泛型等效类。该类使用大小可按需动态增加的数组实现 ilist 泛型接口,大部分用法都与arraylist相似。
list<t> 是类型安全的,在声明list集合时,必须为其声明list集合内数据的对象类型。
using system; using system.collections.generic; public class example { public static void main() { list<string> dinosaurs = new list<string>(); console.writeline("\ncapacity: {0}", dinosaurs.capacity); dinosaurs.add("tyrannosaurus"); dinosaurs.add("amargasaurus"); dinosaurs.add("mamenchisaurus"); dinosaurs.add("deinonychus"); dinosaurs.add("compsognathus"); console.writeline(); foreach(string dinosaur in dinosaurs) { console.writeline(dinosaur); } console.writeline("\ncapacity: {0}", dinosaurs.capacity); console.writeline("count: {0}", dinosaurs.count); console.writeline("\ncontains(\"deinonychus\"): {0}", dinosaurs.contains("deinonychus")); console.writeline("\ninsert(2, \"compsognathus\")"); dinosaurs.insert(2, "compsognathus"); console.writeline(); foreach(string dinosaur in dinosaurs) { console.writeline(dinosaur); } console.writeline("\ndinosaurs[3]: {0}", dinosaurs[3]); console.writeline("\nremove(\"compsognathus\")"); dinosaurs.remove("compsognathus"); console.writeline(); foreach(string dinosaur in dinosaurs) { console.writeline(dinosaur); } dinosaurs.trimexcess(); console.writeline("\ntrimexcess()"); console.writeline("capacity: {0}", dinosaurs.capacity); console.writeline("count: {0}", dinosaurs.count); dinosaurs.clear(); console.writeline("\nclear()"); console.writeline("capacity: {0}", dinosaurs.capacity); console.writeline("count: {0}", dinosaurs.count); } }
如果声明list集合内数据的对象类型是string,然后往list集合中插入int类型的111,ide就会报错,且不能通过编译。显然这样list<t>是类型安全的。
对返回结果集再封装:
public class resultdto<t> { public t data { get; set; } public string code { get; set; } public string message { get; set; } } var data = new cityentity(); return new resultdto<cityentity> { data = data, code = "1", message = "sucess"}; var data2 = new list<cityentity>(); return new resultdto<list<cityentity>> { data = data2, code = "1", message = "sucess" }; var data1 = 1; return new resultdto<int> { data = data1, code = "1", message = "sucess" };
更多参考微软官方文档:list泛型类
四、总结
1、数组的容量固定,而arraylist或list<t>的容量可根据需要自动扩充。
2、数组可有多个维度,而 arraylist或 list< t> 始终只有一个维度。(可以创建数组列表或列表的列表)
3、特定类型的数组性能优于 arraylist的性能(不包括object,因为 arraylist的元素是 object ,在存储或检索值类型时通常发生装箱和取消装箱操作)。
4、 arraylist 和 list<t>基本等效,如果list< t> 类的类型t是引用类型,则两个类的行为是完全相同的。如果t是值类型,需要考虑装箱和拆箱造成的性能损耗。list<t> 是类型安全。