An array represents a fixed number of elements of a particular type. The elements in an array are always stored in a contiguous block of memory, providing highly efficient access.
An array is denoted with square brackets after the element type. The following declares an array of 5 characters:
char[] vowels = new char[5];
Square brackets also index the array, accessing a particular element by position:
vowels[0] = 'a'; vowels[1] = 'e'; vowels[2] = 'i'; vowels[3] = 'o'; vowels[4] = 'u'; Console.WriteLine (vowels [1]); // e
This prints “e” because array indexes start at 0. We can use a
for
loop statement to iterate through
each element in the array. The for
loop
in this example cycles the integer i
from 0
to 4
:
for (int i = 0; i < vowels.Length; i++) Console.Write (vowels [i]); // aeiou
Arrays also implement IEnumerable<T>
(see Enumeration and Iterators), so you can also enumerate members
with the foreach
statement:
foreach (char c in vowels) Console.Write (c); // aeiou
All array indexing is bounds-checked by the runtime. An IndexOutOfRangeException
is thrown if you use an invalid index:
vowels[5] = 'y'; // Runtime error
The Length
property of an
array returns the number of elements in the array. Once an array has been
created, its length cannot be changed. The System.Collection
namespace and subnamespaces provide higher-level data
structures, such as dynamically sized arrays and dictionaries.
An array initialization expression lets you declare and populate an array in a single step:
char[] vowels = new char[] {'a','e','i','o','u'};
or simply:
char[] vowels = {'a','e','i','o','u'};
All arrays inherit from the System.Array
class, which defines common methods
and properties for all arrays. This includes instance properties such as
Length
and Rank
, and static methods to:
Creating an array always pre-initializes the elements with default
values. The default value for a type is the result of a bitwise zeroing
of memory. For example, consider creating an array of integers. Since
int
is a value type, this allocates
1,000 integers in one contiguous block of memory. The default value for
each element will be 0:
int[] a = new int[1000]; Console.Write (a[123]); // 0
With reference-type elements, the default value is null
.
An array itself is always a reference type object, regardless of element type. For instance, the following is legal:
int[] a = null;
Multidimensional arrays come in two varieties: rectangular and jagged. Rectangular arrays represent an n-dimensional block of memory, and jagged arrays are arrays of arrays.
Rectangular arrays are declared using commas to separate each dimension. The following declares a rectangular two-dimensional array, where the dimensions are 3 × 3:
int[,] matrix = new int [3, 3];
The GetLength
method of an
array returns the length for a given dimension (starting at 0):
for (int i = 0; i < matrix.GetLength(0); i++) for (int j = 0; j < matrix.GetLength(1); j++) matrix [i, j] = i * 3 + j;
A rectangular array can be initialized as follows (each element in this example is initialized to be identical to the previous example):
int[,] matrix = new int[,]
{
{0,1,2},
{3,4,5},
{6,7,8}
};
(The code shown in boldface can be omitted in declaration statements such as the one above.)
Jagged arrays are declared using successive square brackets to represent each dimension. Here is an example of declaring a jagged two-dimensional array, where the outermost dimension is 3:
int[][] matrix = new int[3][];
The inner dimensions aren’t specified in the declaration. Unlike a rectangular array, each inner array can be an arbitrary length. Each inner array is implicitly initialized to null rather than an empty array. Each inner array must be created manually:
for (int i = 0; i < matrix.Length; i++) { matrix[i] = new int [3]; // Create inner array for (int j = 0; j < matrix[i].Length; j++) matrix[i][j] = i * 3 + j; }
A jagged array can be initialized as follows (each element in this example is initialized to be identical to the previous example):
int[][] matrix = new int[][]
{
new int[] {0,1,2},
new int[] {3,4,5},
new int[] {6,7,8}
};
(The code shown in boldface can be omitted in declaration statements such as the above.)
We’ve already seen how to simplify array initialization
expressions by omitting the new
keyword and type declaration:
char[] vowels = new char[] {'a','e','i','o','u'}; char[] vowels = {'a','e','i','o','u'};
Another approach is to omit the type name after the new
keyword, and have the compiler
infer the array type. This is a useful shortcut
when passing arrays as arguments. For example, consider the following
method:
void Foo (char[] data) { ... }
We can call this method with an array that we create on the fly, as follows:
Foo (new char[] {'a','e','i','o','u'}
); // Longhand Foo (new[] {'a','e','i','o','u'}
); // Shortcut
This shortcut is essential in creating arrays of anonymous types, as we’ll see later.