特性
數組是一個無序的元素序列。數組元素存儲在一個連續性的內存塊中,並可使用一個整數索引來訪問。
C# 聲明數組變量時,數組的大小不是聲明的一部分。這點與C/C++有些區別。
int[] dogs; // 聲明數組 // 聲明時不需要指定數組的大小
只有在實際創建數組實例的時候,才需要指定數組的大小。創建數組實例時編譯器默認將數組元素初始化為0,null,false(依元素類型不同)。
pins = new int[4]; // 只有在實際創建數組實例的時候,才需要指定數組的大小。
以上兩個語句運行后結果如下:
數組實例的大小不一定是常量,它可以在運行時計算。
int size = int.Parse(Console.ReadLine()); int[] pins = new int[size];
某些情況下,數組大小可能為 0,這個設計是有意義的。大小為 0 的數組不是一個 null(空)數組。除了基本數據類型,數組元素還可以是結構、枚舉或者類。
大括號中的值不一定是常量,它們可以是在運行時計算的值。
Random r = new Random(); int[] pins = new int[4]{r.Next()%10, r.Next()%10, r.Next()%10, r.Next()%10};
初始化
初始化數組變量。大括號中的值的數量必須和要創建的數組實例的大小完全匹配!
int[] pins = new int[3] { 1, 2, 3, 4 }; // 編譯時錯誤 int[] pins = new int[4] { 1, 2, 3 }; // 編譯時錯誤 int[] pins = new int[4] { 1, 2, 3, 4 }; // 正確
初始化一個數組變量時,實際上可省略 new 表達式和數組的大小,編譯器將根據初始值的數量來計算大小。
int[] pins = { 1, 2, 3, 4 }; // 正確
創建一個由結構構成的數組時,為了初始化數組的每個結構,可以調用結構構造器。
struct Time { private int hours, minutes, seconds; public Time(int hh, int mm) { hours = hh; minutes = mm; seconds = 0; } } Time[] schedule = {new Time(12, 30), new Time(5, 30)}; // 調用自定義的結構構造器
隱式類型的數組創建
匿名類(anonymous class)是一個沒有名字的類,只能包含 public 字段,字段必須全部初始化,不可以是 static 字段,而且不能在其中指定方法。
可以創建隱式類型的數組。如果在聲明數組的時候指定了一個初始值列表,就可以讓 C# 編譯器自己推斷數組中的元素的類型。
var names = new[]{"Steven", "Lily", "Tom", "Miley"}; // C# 推斷 names 是一個 string 類型 Console.WriteLine(names[0]); Console.WriteLine(names[3]); // 隱式類型轉換的數組尤其適用於匿名類型 var people = new[]{new {Name = "Steven", Age = 27}, new {Name = "Lily", Age = 25}, new {Name = "Tom", Age = 8}, new {Name = "Miley", Age = 6}}; // 數組中的每個元素都是匿名類型 // 並且每個元素都必須指定相同的匿名類型
訪問及遍歷數組有如下方法,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace arrayType { class Program { static void Main(string[] args) { string[] names = new[]{"Steven", "Lily", "Tom", "Miley"}; Console.WriteLine(names[0]); Console.WriteLine(names[3]); Console.WriteLine(); Console.WriteLine("用 for 遍歷字符串數組"); for (int i = 0; i < names.Length; i++) // length 是屬性而不是方法,不要加 '()' { Console.WriteLine(names[i]); } Console.WriteLine(); Console.WriteLine("用 foreach 遍歷 string 數組"); // foreach 是遍歷數組的首選方式 foreach(string name in names) { Console.WriteLine(name); } var people = new[]{new {Name = "Steven", Age = 27}, new {Name = "Lily", Age = 25}, new {Name = "Tom", Age = 8}, new {Name = "Miley", Age = 6}}; Console.WriteLine(); Console.WriteLine("用 foreach 遍歷 var 數組"); foreach(var person in people) { Console.WriteLine(person); } Console.WriteLine(); Console.WriteLine("用 foreach 遍歷 var 數組"); foreach (var person in people) { Console.WriteLine("Name: {0}, Age: {1}", person.Name, person.Age); } Console.WriteLine(); } } }
復制數組
復制數組有如下方法,但只有最后一種是真正的復制。
int[] pins = { 1, 2, 3, 4 }; int[] copy = new int[pins.Length]; pins.CopyTo(copy, 0); // 將數組 pins 的內容復制到數組 copy // CopyTo 是淺拷貝,從指定位置開始復制,復制后兩個數組都引用同一組對象 int[] pins = { 1, 2, 3, 4 }; int[] copy = new int[pins.Length]; Array.Copy(pins, copy, copy.Length); // Copy 方法是淺拷貝 int[] pins = { 1, 2, 3, 4 }; int[] copy = (int[])pins.Clone(); // Clone 方法是淺拷貝 // Clone 放回的是一個 object,所以必須進行類型准換 int[] pins = { 1, 2, 3, 4 }; int[] copy = new int[pins.Length]; for (int i = 0; i < copy.Length; i++) { copy[i] = pins[i]; // 深拷貝,也就是產生了兩個數組 }
維數
數組的維數是沒有限制的,可以創建多維數組。
string[,] stars = new string[6,8]; // 創建二維數組,6 行 8 列 stars[2, 6] = "Mars"; // 將單元格(2, 6)的元素設為 Mars // 使用多維數組時,要准備好捕捉並處理 OutOfMemoryException