陣列

您可以在陣列資料結構中儲存相同類型的多個變數。 您可以指定陣列元素的類型來宣告陣列。 如果您要陣列儲存任何類型的元素,可以指定 object 作為其類型。 在 C# 的統一型別系統中,所有類型 (預先定義和使用者定義的、參考型別和實值型別) 都會直接或間接繼承自 Object

type[] arrayName;

陣列具有下列屬性︰

  • 陣列可以是一維多維不規則
  • 當宣告陣列變數時,會設定維度數。 當建立陣列執行個體時,會建立每個維度的長度。 在執行個體的存留期期間,這些值無法變更。
  • 不規則陣列是陣列的陣列,而每個成員陣列的預設值為 null
  • 陣列為以零為基底索引:具有 n 個元素的陣列,會從 0n-1 編製索引。
  • 陣列元素可以是任何類型,包含陣列類型。
  • 陣列類型是衍生自抽象基底類型 Array參考類型。 所有陣列都會實作 IListIEnumerable。 您可以使用 foreach 陳述式逐一查看陣列。 一維陣列也會實作 IList<T>IEnumerable<T>

當建立陣列時,可以將陣列元素初始化為已知值。 從 C# 12 開始,所有集合型別都可以使用集合運算式進行初始化。 未初始化的元素會設定為預設值。 預設值為 0 位元模式。 所有參考型別 (包括 不可為 Null 型別) 都具有值 null。 所有實值型別都有 0 位元模式。 這表示 Nullable<T>.HasValue 屬性為 false,且 Nullable<T>.Value 屬性尚未定義。 在 .NET 實作中,Value 屬性會擲回例外狀況。

下列範例會建立一維陣列、多維陣列和不規則陣列︰

// Declare a single-dimensional array of 5 integers.
int[] array1 = new int[5];

// Declare and set array element values.
int[] array2 = [1, 2, 3, 4, 5, 6];

// Declare a two dimensional array.
int[,] multiDimensionalArray1 = new int[2, 3];

// Declare and set array element values.
int[,] multiDimensionalArray2 = { { 1, 2, 3 }, { 4, 5, 6 } };

// Declare a jagged array.
int[][] jaggedArray = new int[6][];

// Set the values of the first array in the jagged array structure.
jaggedArray[0] = [1, 2, 3, 4];

一維陣列

一維陣列是類似元素的序列。 您可以透過其元素索引來存取元素。 索引是其在序列中的序數位置。 陣列中的第一個元素是位於索引 0。 您會使用指定陣列元素類型與元素數目的運算子,建立單一維度陣列。 下列範例會宣告和初始化一維陣列:

int[] array = new int[5];
string[] weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

Console.WriteLine(weekDays[0]);
Console.WriteLine(weekDays[1]);
Console.WriteLine(weekDays[2]);
Console.WriteLine(weekDays[3]);
Console.WriteLine(weekDays[4]);
Console.WriteLine(weekDays[5]);
Console.WriteLine(weekDays[6]);

/*Output:
Sun
Mon
Tue
Wed
Thu
Fri
Sat
*/

第一個宣告會宣告五個整數的未初始化陣列,從 array[0]array[4]。 陣列的元素會初始化為元素類型的預設值0 代表整數。 第二個宣告會宣告字串陣列,並初始化該陣列的所有七個值。 一系列的 Console.WriteLine 陳述式會列印 weekDay 陣列的所有元素。 針對一維陣列,foreach 陳述式會以遞增索引順序處理元素,從索引 0 開始並於索引 Length - 1 結束。

將一維陣列作為引數傳遞

您可以將初始化的一維陣列傳遞至方法。 在下列範例中,字串的陣列會初始化,並作為引數傳遞至字串的 DisplayArray 方法。 此方法會顯示陣列的元素。 接下來,ChangeArray 方法會反轉陣列項目,然後 ChangeArrayElements 方法會修改陣列的前三個項目。 每個方法傳回之後,DisplayArray 方法會顯示以傳值方式傳遞陣列不會防止變更陣列元素。

class ArrayExample
{
    static void DisplayArray(string[] arr) => Console.WriteLine(string.Join(" ", arr));

    // Change the array by reversing its elements.
    static void ChangeArray(string[] arr) => Array.Reverse(arr);

    static void ChangeArrayElements(string[] arr)
    {
        // Change the value of the first three array elements.
        arr[0] = "Mon";
        arr[1] = "Wed";
        arr[2] = "Fri";
    }

    static void Main()
    {
        // Declare and initialize an array.
        string[] weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
        // Display the array elements.
        DisplayArray(weekDays);
        Console.WriteLine();

        // Reverse the array.
        ChangeArray(weekDays);
        // Display the array again to verify that it stays reversed.
        Console.WriteLine("Array weekDays after the call to ChangeArray:");
        DisplayArray(weekDays);
        Console.WriteLine();

        // Assign new values to individual array elements.
        ChangeArrayElements(weekDays);
        // Display the array again to verify that it has changed.
        Console.WriteLine("Array weekDays after the call to ChangeArrayElements:");
        DisplayArray(weekDays);
    }
}
// The example displays the following output:
//         Sun Mon Tue Wed Thu Fri Sat
//
//        Array weekDays after the call to ChangeArray:
//        Sat Fri Thu Wed Tue Mon Sun
//
//        Array weekDays after the call to ChangeArrayElements:
//        Mon Wed Fri Wed Tue Mon Sun

多維陣列

陣列可以有多個維度。 例如,下列宣告會建立四個陣列:二有二維度,二有三維度。 前兩個宣告會宣告每個維度的長度,但不會初始化陣列的值。 後二個兩個宣告會使用初始設定式來設定多維度陣列中每個元素的值。

int[,] array2DDeclaration = new int[4, 2];

int[,,] array3DDeclaration = new int[4, 2, 3];

// Two-dimensional array.
int[,] array2DInitialization =  { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// Three-dimensional array.
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4,   5,  6 } },
                                { { 7, 8, 9 }, { 10, 11, 12 } } };

// Accessing array elements.
System.Console.WriteLine(array2DInitialization[0, 0]);
System.Console.WriteLine(array2DInitialization[0, 1]);
System.Console.WriteLine(array2DInitialization[1, 0]);
System.Console.WriteLine(array2DInitialization[1, 1]);

System.Console.WriteLine(array2DInitialization[3, 0]);
System.Console.WriteLine(array2DInitialization[3, 1]);
// Output:
// 1
// 2
// 3
// 4
// 7
// 8

System.Console.WriteLine(array3D[1, 0, 1]);
System.Console.WriteLine(array3D[1, 1, 2]);
// Output:
// 8
// 12

// Getting the total count of elements or the length of a given dimension.
var allLength = array3D.Length;
var total = 1;
for (int i = 0; i < array3D.Rank; i++)
{
    total *= array3D.GetLength(i);
}
System.Console.WriteLine($"{allLength} equals {total}");
// Output:
// 12 equals 12

針對多維陣列,元素的周遊方式是先遞增最右側維度的索引,然後遞增下一個左側維度,以此類推直至最左側的索引。 下列範例同時列舉了 2D 和 3D 陣列:

int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } };

foreach (int i in numbers2D)
{
    System.Console.Write($"{i} ");
}
// Output: 9 99 3 33 5 55

int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4,   5,  6 } },
                        { { 7, 8, 9 }, { 10, 11, 12 } } };
foreach (int i in array3D)
{
    System.Console.Write($"{i} ");
}
// Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12

在 2D 陣列中,您可以將左側索引視為資料列,並將右側索引視為資料行

但是在使用多維陣列時,使用巢狀 for 迴圈能夠讓您進一步控制處理陣列元素的順序:

int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4,   5,  6 } },
                        { { 7, 8, 9 }, { 10, 11, 12 } } };

for (int i = 0; i < array3D.GetLength(0); i++)
{
    for (int j = 0; j < array3D.GetLength(1); j++)
    {
        for (int k = 0; k < array3D.GetLength(2); k++)
        {
            System.Console.Write($"{array3D[i, j, k]} ");
        }
        System.Console.WriteLine();
    }
    System.Console.WriteLine();
}
// Output (including blank lines): 
// 1 2 3
// 4 5 6
// 
// 7 8 9
// 10 11 12
//

將多維陣列作為引數傳遞

將初始化的多維陣列傳遞至方法所使用的方式,與傳遞一維陣列的方式相同。 下列程式碼顯示可接受二維陣列作為其引數之列印方法的部分宣告。 您可以在一個步驟中初始化並傳遞新的陣列,如下列範例所示。 在下列範例中,整數的二維陣列會初始化並傳遞至 Print2DArray 方法。 此方法會顯示陣列的元素。

static void Print2DArray(int[,] arr)
{
    // Display the array elements.
    for (int i = 0; i < arr.GetLength(0); i++)
    {
        for (int j = 0; j < arr.GetLength(1); j++)
        {
            System.Console.WriteLine("Element({0},{1})={2}", i, j, arr[i, j]);
        }
    }
}
static void ExampleUsage()
{
    // Pass the array as an argument.
    Print2DArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });
}
/* Output:
    Element(0,0)=1
    Element(0,1)=2
    Element(1,0)=3
    Element(1,1)=4
    Element(2,0)=5
    Element(2,1)=6
    Element(3,0)=7
    Element(3,1)=8
*/

不規則陣列

不規則陣列的元素是大小可能各異的陣列。 不規則陣列有時稱為「陣列的陣列」。其元素是參考型別,而且會初始化為 null。 下列範例示範如何宣告、初始化和存取不規則陣列。 第一個範例 jaggedArray 是一個陳述式中進行宣告。 每個包含的陣列會在後續陳述式中建立。 第二個範例 jaggedArray2 是在一個陳述式中進行宣告和初始化。 混合使用不規則陣列與多維陣列是可行的。 最後一個範例 jaggedArray3 是一維不規則陣列的宣告和初始化,而此陣列包含三個不同大小的二維陣列元素。

int[][] jaggedArray = new int[3][];

jaggedArray[0] = [1, 3, 5, 7, 9];
jaggedArray[1] = [0, 2, 4, 6];
jaggedArray[2] = [11, 22];

int[][] jaggedArray2 = 
[
    [1, 3, 5, 7, 9],
    [0, 2, 4, 6],
    [11, 22]
];

// Assign 77 to the second element ([1]) of the first array ([0]):
jaggedArray2[0][1] = 77;

// Assign 88 to the second element ([1]) of the third array ([2]):
jaggedArray2[2][1] = 88;

int[][,] jaggedArray3 =
[
    new int[,] { {1,3}, {5,7} },
    new int[,] { {0,2}, {4,6}, {8,10} },
    new int[,] { {11,22}, {99,88}, {0,9} }
];

Console.Write("{0}", jaggedArray3[0][1, 0]);
Console.WriteLine(jaggedArray3.Length);

您必須先初始化不規則陣列的元素,才能使用這些元素。 每個元素本身都是陣列。 您也可以使用初始設定式將值填入陣列元素中。 當您使用初始設定式時,就不需要陣列大小。

此範例會建置其項目本身為陣列的陣列。 每個陣列元素都會有不同的大小。

// Declare the array of two elements.
int[][] arr = new int[2][];

// Initialize the elements.
arr[0] = [1, 3, 5, 7, 9];
arr[1] = [2, 4, 6, 8];

// Display the array elements.
for (int i = 0; i < arr.Length; i++)
{
    System.Console.Write("Element({0}): ", i);

    for (int j = 0; j < arr[i].Length; j++)
    {
        System.Console.Write("{0}{1}", arr[i][j], j == (arr[i].Length - 1) ? "" : " ");
    }
    System.Console.WriteLine();
}
/* Output:
    Element(0): 1 3 5 7 9
    Element(1): 2 4 6 8
*/

隱含型別陣列

您可以建立隱含型別的陣列,其中陣列執行個體的型別是從陣列初始設定式中所指定的元素推斷而來。 任何隱含型別的變數規則也適用於隱含型別的陣列。 如需詳細資訊,請參閱隱含型別區域變數

下列範例示範如何建立隱含型別陣列:

int[] a = new[] { 1, 10, 100, 1000 }; // int[]

// Accessing array
Console.WriteLine("First element: " + a[0]);
Console.WriteLine("Second element: " + a[1]);
Console.WriteLine("Third element: " + a[2]);
Console.WriteLine("Fourth element: " + a[3]);
/* Outputs
First element: 1
Second element: 10
Third element: 100
Fourth element: 1000
*/

var b = new[] { "hello", null, "world" }; // string[]

// Accessing elements of an array using 'string.Join' method
Console.WriteLine(string.Join(" ", b));
/* Output
hello  world
*/

// single-dimension jagged array
int[][] c =
[
    [1,2,3,4],
    [5,6,7,8]
];
// Looping through the outer array
for (int k = 0; k < c.Length; k++)
{
    // Looping through each inner array
    for (int j = 0; j < c[k].Length; j++)
    {
        // Accessing each element and printing it to the console
        Console.WriteLine($"Element at c[{k}][{j}] is: {c[k][j]}");
    }
}
/* Outputs
Element at c[0][0] is: 1
Element at c[0][1] is: 2
Element at c[0][2] is: 3
Element at c[0][3] is: 4
Element at c[1][0] is: 5
Element at c[1][1] is: 6
Element at c[1][2] is: 7
Element at c[1][3] is: 8
*/

// jagged array of strings
string[][] d =
[
    ["Luca", "Mads", "Luke", "Dinesh"],
    ["Karen", "Suma", "Frances"]
];

// Looping through the outer array
int i = 0;
foreach (var subArray in d)
{
    // Looping through each inner array
    int j = 0;
    foreach (var element in subArray)
    {
        // Accessing each element and printing it to the console
        Console.WriteLine($"Element at d[{i}][{j}] is: {element}");
        j++;
    }
    i++;
}
/* Outputs
Element at d[0][0] is: Luca
Element at d[0][1] is: Mads
Element at d[0][2] is: Luke
Element at d[0][3] is: Dinesh
Element at d[1][0] is: Karen
Element at d[1][1] is: Suma
Element at d[1][2] is: Frances
*/

在上述範例中,請注意,使用隱含型別陣列時,在初始化陳述式左側並未使用方括弧。 也請注意不規則陣列是使用 new [] 進行初始化,就像一維陣列一樣。

當您建立包含陣列的匿名型別時,在類型的物件初始設定式中,陣列必須是隱含型別。 在下列範例中,contacts 是隱含型別的匿名型別陣列,每個都會包含名為 PhoneNumbers 的陣列。 var 關鍵字並未在物件初始設定式內使用。

var contacts = new[]
{
    new
    {
        Name = "Eugene Zabokritski",
        PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
    },
    new
    {
        Name = "Hanying Feng",
        PhoneNumbers = new[] { "650-555-0199" }
    }
};