Arrays
You can store multiple variables of the same type in an array data structure. You declare an array by specifying the type of its elements. If you want the array to store elements of any type, you can specify object
as its type. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object.
type[] arrayName;
An array is a reference type, so the array can be a nullable reference type. The element types might be reference types, so an array can be declared to hold nullable reference types. The following example declarations show the different syntax used to declare the nullability of the array or the elements:
type?[] arrayName; // non nullable array of nullable element types.
type[]? arrayName; // nullable array of non-nullable element types.
type?[]? arrayName; // nullable array of nullable element types.
Uninitialized elements in an array are set to the default value for that type:
int[] numbers = new int[10]; // All values are 0
string[] messages = new string[10]; // All values are null.
Important
In the preceding example, even though the type is string[]
, an array of non-nullable strings, the default value for each element is null. The best way to initialize an array to non-null values is to use a collection expressions.
An array has the following properties:
- An array can be single-dimensional, multidimensional, or jagged.
- The number of dimensions are set when an array variable is declared. The length of each dimension is established when the array instance is created. These values can't be changed during the lifetime of the instance.
- A jagged array is an array of arrays, and each member array has the default value of
null
. - Arrays are zero indexed: an array with
n
elements is indexed from0
ton-1
. - Array elements can be of any type, including an array type.
- Array types are reference types derived from the abstract base type Array. All arrays implement IList and IEnumerable. You can use the foreach statement to iterate through an array. Single-dimensional arrays also implement IList<T> and IEnumerable<T>.
The elements of an array can be initialized to known values when the array is created. Beginning with C# 12, all of the collection types can be initialized using a Collection expression. Elements that aren't initialized are set to the default value. The default value is the 0-bit pattern. All reference types (including non-nullable types), have the values null
. All value types have the 0-bit patterns. That means the Nullable<T>.HasValue property is false
and the Nullable<T>.Value property is undefined. In the .NET implementation, the Value
property throws an exception.
The following example creates single-dimensional, multidimensional, and jagged arrays:
// 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];
Important
Many of the examples in this article use collection expressions (which use square brackets) to initialize the arrays. Collection expressions were first introduced in C# 12, which shipped with .NET 8. If you can't upgrade to C# 12 yet, use {
and }
to initialize the arrays instead.
// Collection expressions:
int[] array = [1, 2, 3, 4, 5, 6];
// Alternative syntax:
int[] array2 = {1, 2, 3, 4, 5, 6};
Single-dimensional arrays
A single-dimensional array is a sequence of like elements. You access an element via its index. The index is its ordinal position in the sequence. The first element in the array is at index 0
. You create a single-dimensional array using the new operator specifying the array element type and the number of elements. The following example declares and initializes single-dimensional arrays:
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
*/
The first declaration declares an uninitialized array of five integers, from array[0]
to array[4]
. The elements of the array are initialized to the default value of the element type, 0
for integers. The second declaration declares an array of strings and initializes all seven values of that array. A series of Console.WriteLine
statements prints all the elements of the weekDay
array. For single-dimensional arrays, the foreach
statement processes elements in increasing index order, starting with index 0 and ending with index Length - 1
.
Pass single-dimensional arrays as arguments
You can pass an initialized single-dimensional array to a method. In the following example, an array of strings is initialized and passed as an argument to a DisplayArray
method for strings. The method displays the elements of the array. Next, the ChangeArray
method reverses the array elements, and then the ChangeArrayElements
method modifies the first three elements of the array. After each method returns, the DisplayArray
method shows that passing an array by value doesn't prevent changes to the array elements.
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
Multidimensional arrays
Arrays can have more than one dimension. For example, the following declarations create four arrays. Two arrays have have two dimensions. Two arrays have three dimensions. The first two declarations declare the length of each dimension, but don't initialize the values of the array. The second two declarations use an initializer to set the values of each element in the multidimensional array.
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
For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are incremented first, then the next left dimension, and so on, to the leftmost index. The following example enumerates both a 2D and a 3D array:
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
In a 2D array, you can think of the left index as the row and the right index as the column.
However, with multidimensional arrays, using a nested for loop gives you more control over the order in which to process the array elements:
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
//
Pass multidimensional arrays as arguments
You pass an initialized multidimensional array to a method in the same way that you pass a one-dimensional array. The following code shows a partial declaration of a print method that accepts a two-dimensional array as its argument. You can initialize and pass a new array in one step, as is shown in the following example. In the following example, a two-dimensional array of integers is initialized and passed to the Print2DArray
method. The method displays the elements of the array.
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
*/
Jagged arrays
A jagged array is an array whose elements are arrays, possibly of different sizes. A jagged array is sometimes called an "array of arrays." Its elements are reference types and are initialized to null
. The following examples show how to declare, initialize, and access jagged arrays. The first example, jaggedArray
, is declared in one statement. Each contained array is created in subsequent statements. The second example, jaggedArray2
is declared and initialized in one statement. It's possible to mix jagged and multidimensional arrays. The final example, jaggedArray3
, is a declaration and initialization of a single-dimensional jagged array that contains three two-dimensional array elements of different sizes.
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);
A jagged array's elements must be initialized before you can use them. Each of the elements is itself an array. It's also possible to use initializers to fill the array elements with values. When you use initializers, you don't need the array size.
This example builds an array whose elements are themselves arrays. Each one of the array elements has a different size.
// 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
*/
Implicitly typed arrays
You can create an implicitly typed array in which the type of the array instance is inferred from the elements specified in the array initializer. The rules for any implicitly typed variable also apply to implicitly typed arrays. For more information, see Implicitly Typed Local Variables.
The following examples show how to create an implicitly typed array:
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
*/
In the previous example, notice that with implicitly typed arrays, no square brackets are used on the left side of the initialization statement. Also, jagged arrays are initialized by using new []
just like single-dimensional arrays.
When you create an anonymous type that contains an array, the array must be implicitly typed in the type's object initializer. In the following example, contacts
is an implicitly typed array of anonymous types, each of which contains an array named PhoneNumbers
. The var
keyword isn't used inside the object initializers.
var contacts = new[]
{
new
{
Name = "Eugene Zabokritski",
PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
},
new
{
Name = "Hanying Feng",
PhoneNumbers = new[] { "650-555-0199" }
}
};