在C#中陣列Array,ArrayList,泛型List都能夠儲存一組物件,但是在開發中根本不知道用哪個效能最高,下面我們慢慢分析分析。
一、陣列Array
陣列是一個儲存相同型別元素的固定大小的順序集合。陣列是用來儲存資料的集合,通常認為陣列是一個同一型別變數的集合。
Array 類是 C# 中所有陣列的基類,它是在 System 名稱空間中定義。
陣列在記憶體中是連續儲存的,所以它的索引速度非常快,而且賦值與修改元素也非常簡單。
Array陣列具體用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
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 屬性減少容量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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解決了陣列中所有的缺點,但是在儲存或檢索值型別時通常發生裝箱和取消裝箱操作,帶來很大的效能耗損。尤其是裝箱操作,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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集合內資料的物件型別。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
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>是型別安全的。
對返回結果集再封裝:
1 2 3 4 5 6 |
public class ResultDTO<T> { public T Data { get; set; } public string Code { get; set; } public string Message { get; set; } } |
1 2 3 4 5 6 7 8 |
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> 是型別安全。