Skip to content

C# - Arrays

In C#, an array is a fundamental data structure that stores a fixed-size, sequential collection of elements of the same type. Think of it as a numbered list of boxes, where each box holds the same kind of item and can be accessed by its number (or index). Arrays are stored in a contiguous block of memory, which makes accessing elements by index very fast.

While you could declare individual variables like score1, score2, score3, it’s far more efficient to use an array: scores. You can then access individual elements using an index, like scores[0], scores[1], and scores[2]. Note that array indices in C# are zero-based, meaning the first element is at index 0.

You declare an array by specifying the element type, followed by square brackets []. Initialization is the process of allocating memory and providing initial values.

Here are the common ways to declare and initialize an array:

// 1. Declare and initialize with a specific size (elements get default values, e.g., 0 for int)
int[] numbers = new int[5];
// 2. Declare and initialize with values (compiler infers the size)
double[] balances = { 2340.0, 4523.69, 3421.0 };
// 3. Using the 'new' keyword with an initializer list
string[] names = new string[] { "Alice", "Bob", "Charlie" };
// 4. Using a target-typed 'new' expression (C# 9 and later)
char[] vowels = new[] { 'a', 'e', 'i', 'o', 'u' };

When you create an array, C# initializes each element to its default value. For numeric types it’s 0, for bool it’s false, and for reference types (like string) it’s null.

You access and modify array elements using their zero-based index inside square brackets.

string[] names = { "Alice", "Bob", "Charlie" };
// Access the first element
string firstName = names[0]; // "Alice"
// Modify the second element
names[1] = "Barbara";
Console.WriteLine($"The names are: {names[0]}, {names[1]}, {names[2]}");
// Output: The names are: Alice, Barbara, Charlie

A common mistake is trying to access an element outside the valid index range. An array of length 3 has valid indices 0, 1, and 2. Accessing names[3] would throw an IndexOutOfRangeException.

// This will cause a runtime error!
// string errorName = names[3];

Looping through array elements is a common task. The foreach loop is the simplest and safest way to do this.

The foreach loop iterates over each element in the collection without needing to manage an index variable.

using System;
int[] scores = { 99, 98, 92, 97, 95 };
Console.WriteLine("Student Scores:");
foreach (int score in scores)
{
Console.WriteLine(score);
}

A for loop is useful when you need access to the element’s index during iteration.

using System;
string[] fruits = { "Apple", "Banana", "Cherry" };
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine($"Fruit at index {i}: {fruits[i]}");
}

The Length property gives the total number of elements in the array. In the for loop, the condition i < fruits.Length prevents an IndexOutOfRangeException.

The System.Array class and LINQ (Language-Integrated Query) provide powerful methods for working with arrays.

You can sort an array in place using Array.Sort().

int[] numbers = { 50, 20, 40, 10, 30 };
// Sorts in ascending order
Array.Sort(numbers);
// To sort in descending order, sort then reverse
Array.Reverse(numbers);
Console.WriteLine(string.Join(", ", numbers)); // Output: 50, 40, 30, 20, 10

For more flexibility, especially when you don’t want to modify the original array, you can use LINQ. You will need to add using System.Linq;.

using System.Linq;
int[] originalNumbers = { 50, 20, 40, 10, 30 };
// LINQ methods return a new sequence, they don't modify the original
var sortedAscending = originalNumbers.OrderBy(n => n).ToArray();
var sortedDescending = originalNumbers.OrderByDescending(n => n).ToArray();
Console.WriteLine($"Ascending: {string.Join(", ", sortedAscending)}");
Console.WriteLine($"Descending: {string.Join(", ", sortedDescending)}");

Assigning an array variable to another does not create a copy; both variables will point to the same array in memory.

int[] original = { 1, 2, 3 };
int[] referenceCopy = original; // Not a real copy
referenceCopy[0] = 99;
Console.WriteLine(original[0]); // Output: 99

To create a true, independent copy (a shallow copy), you can use LINQ’s ToArray() method or Array.Copy().

using System.Linq;
int[] sourceArray = { 1, 2, 3, 4, 5 };
// Modern way using LINQ
int[] newCopy = sourceArray.ToArray();
// Traditional way
int[] destinationArray = new int[sourceArray.Length];
Array.Copy(sourceArray, destinationArray, sourceArray.Length);
newCopy[0] = 100;
Console.WriteLine($"Source: {sourceArray[0]}"); // Output: Source: 1
Console.WriteLine($"New Copy: {newCopy[0]}"); // Output: New Copy: 100

Arrays are great for performance when you have a fixed number of elements. However, for collections that need to grow or shrink dynamically, other types are often better.

TypeDescription
Array (int[])Fixed-size. Best performance for access by index. Use when the collection size is known and won’t change.
List (List<int>)Dynamically-sized. The most common general-purpose collection. Provides methods like Add(), Remove(), and Sort().
Multi-dimensional Array (int[,])A rectangular array (e.g., a grid or matrix). All rows must have the same length.
Jagged Array (int[][])An array of arrays. Each inner array can have a different length.

For new developers, it’s often best to start with List<T>. It’s more flexible than an array and is used extensively in modern .NET applications. You can easily convert between a List<T> and an array using .ToList() and .ToArray().