Back to Blog
C#

C# Array Declaration: Syntax and Usage

Understand C# array declaration syntax, initialization patterns, and the tradeoffs between arrays and List.

C# arraysarray initializationjagged arraysmultidimensional arraysimplicit typingarray vs List
A visual metaphor for C# array declaration showing a row of indexed boxes representing a fixed-size array.

When you create an array in C#, you are allocating a fixed-size block of memory on the heap. The syntax is straightforward, but the choices you make during declaration affect type safety, performance, and maintainability. This article covers the core C# array declaration patterns and the tradeoffs involved.

Basic Array Declaration Syntax

The most common way to declare an array is to specify the element type followed by square brackets, then assign a new array instance with a given length:

int[] numbers = new int[5];

This creates an array of five integers, each initialized to the default value for int, which is 0. The variable numbers holds a reference to the array object. The length is fixed at creation time and cannot be changed later.

You can also separate declaration from assignment:

int[] numbers; numbers = new int[5];

This is useful when the array is assigned conditionally or passed as an argument. The declared variable is null until you assign an array to it.

Initializing Arrays with Values

If you know the values at compile time, you can use an array initializer:

int[] primes = { 2, 3, 5, 7, 11 };

The compiler infers the length from the number of elements. You can also use the new keyword with the initializer:

int[] primes = new int[] { 2, 3, 5, 7, 11 };

Both forms are equivalent. The shorter form is idiomatic, but the explicit new int[] makes the element type clear when it is not obvious from the surrounding context, such as with var.

Multidimensional and Jagged Arrays

C# supports two distinct kinds of multi-dimensional arrays: rectangular and jagged.

A rectangular array has a fixed number of rows and columns, and is declared with a comma inside the brackets:

int[,] matrix = new int[3, 4];

This creates a 3x4 matrix. All rows have the same length, and memory is allocated as a single contiguous block.

A jagged array is an array of arrays, where each inner array can have a different length:

int[][] jagged = new int[3][]; jagged[0] = new int[4]; jagged[1] = new int[2]; jagged[2] = new int[6];

Jagged arrays are more flexible but require separate allocation for each inner array. Access syntax also differs: matrix[1,2] for rectangular, jagged[1][2] for jagged.

Using var for Array Declaration

The var keyword lets you declare an array without writing the type explicitly:

var numbers = new[] { 10, 20, 30, 40 };

The compiler infers the element type from the initializer. This works well when the type is obvious, but it can reduce readability if the initializer is complex. If you need to declare an empty array, you must still specify the element type, because var requires an initializer that provides a type.

Array vs List: When to Use Which

Arrays and List<T> both store sequences of elements, but they differ in resizability and allocation behavior. An array has a fixed size; a List<T> can grow dynamically. List<T> internally uses an array and resizes it when needed, which involves copying the existing elements.

FeatureArrayList<T>
SizeFixed at creationDynamic
Memory overheadMinimalSlight overhead
Resize costNot applicableO(n) on resize
Index accessO(1)O(1)
Type safetyStrongStrong

Use an array when the number of elements is known and fixed, and when you need the lowest possible memory overhead. Use a List<T> when the collection size changes at runtime, or when you need methods like Add, Remove, or Contains without implementing them manually.

Common Mistakes and Edge Cases

A frequent mistake is forgetting that arrays are zero-based. Accessing numbers[5] on an array of length 5 throws an IndexOutOfRangeException. Always check the Length property or use for loops with i < array.Length.

Another subtle issue is array covariance. In C#, an array of a reference type can be assigned to an array of its base type:

string[] strings = new string[10]; object[] objects = strings;

This is allowed, but it can lead to runtime errors if you try to assign a non-string object to objects[0]. The runtime throws ArrayTypeMismatchException because the underlying array is still a string[].

Empty arrays are also a common source of confusion. An empty array has length zero and is not null. You can create one with Array.Empty<T>() to avoid allocating a new empty array each time, which is a small but useful optimization in high-traffic code.

Performance and Memory Considerations

Array allocation happens on the managed heap. The size of the array is fixed at creation, and the runtime reserves a contiguous block of memory. This makes array access very fast, but it also means you cannot change the size without creating a new array and copying the data.

For large arrays, consider the memory footprint. An int[] of length 1,000,000 consumes about 4 MB of element storage, plus a small object header. Like List<T>, arrays store value types inline and avoid boxing. The main difference is that a List<T> may hold extra capacity beyond its Count to reduce future resizes, whereas an array's length is exactly its capacity. So an array can be more memory-efficient when the size is fixed.

When performance is critical, and you know the exact size at compile time or design time, an array avoids the overhead of dynamic resizing and the extra capacity of a List<T>. For example, a fixed lookup table or a buffer used in a tight loop is often better as an array.

C# Array Declaration: Practical Usage and Code Examples | RYUSLOG DEV