C# Arrays

Store fixed-size collections of values in arrays, read and change items by index, loop over them, sort, search, copy and resize them, slice with ranges, and use two-dimensional arrays for grids.

Lesson 9 of 43Intermediate18 min read

When a program works with many values of the same kind, such as twelve monthly sales figures, the scores of a quiz or the seats in a theatre, giving each one its own variable doesn't scale. An array stores a fixed number of values of one type under a single name, and you reach each value by its position, called its index.

Arrays are the simplest and fastest collection in C#. Their size is set when they're created and can't change afterwards, which makes them ideal for data whose size is known, like the days of the week or the pixels of an image. When you need a collection that grows and shrinks, a List<T> is usually a better fit, and it's the subject of the next lesson.

In this lesson you'll create arrays, read and update items, loop through them, use C#'s handy index from end (^1) and range (1..3) syntax, sort and search, understand what happens when you copy an array, and build grids with two-dimensional arrays.

Creating arrays

C#
int[] scores = new int[5];                  // five zeros
string[] days = { "Mon", "Tue", "Wed" };     // initialised with values
double[] temps = new double[] { 18.5, 21.0 };
int[] primes = [2, 3, 5, 7];                 // collection expression (C# 12)
  • The type is written with square brackets: int[] means "array of int".
  • A new array is filled with default values: 0 for numbers, false for bools, and null for strings and other reference types.
  • scores.Length gives the number of items.

Indexes, ranges and loops

Indexes start at 0, so the last item is at Length - 1:

C#
string first = days[0];      // "Mon"
days[1] = "Tuesday";         // change an item
string last = days[^1];      // "Wed", one from the end
string[] middle = days[1..3];  // items 1 and 2
  • Reading or writing outside the array throws an IndexOutOfRangeException.
  • ^1 is the last item, ^2 the second to last.
  • A range start..end includes start and excludes end; ..2 means the first two, 2.. means from index 2 to the end.
  • Use foreach to read every item, and for when you need the index or want to change items.

Sorting, searching and copying

  • Array.Sort(arr) sorts in place; Array.Reverse(arr) reverses.
  • Array.IndexOf(arr, value) returns the position or -1; arr.Contains(value) returns a bool.
  • arr.Max(), arr.Min(), arr.Sum() and arr.Average() come from LINQ.

Arrays are reference types. int[] b = a; doesn't copy the items; both names point to the same array, so changing b[0] changes a[0] too. Use (int[])a.Clone() or a.ToArray() for a real copy. Array.Resize(ref arr, 10) creates a bigger copy when you really need one.

Multidimensional and jagged arrays

A two-dimensional array is a grid with rows and columns:

C#
char[,] board = new char[3, 3];
board[1, 1] = 'X';
int rows = board.GetLength(0);    // 3

A jagged array is an array of arrays, where each row can have a different length: int[][] weeks = new int[4][];. Jagged arrays are more common in everyday code because each row is a normal array you can loop over with foreach.

Comparing and printing arrays

Because arrays are reference types, == checks whether two variables point to the same array, not whether they hold the same values:

C#
int[] a = { 1, 2, 3 };
int[] b = { 1, 2, 3 };
Console.WriteLine(a == b);              // False: two separate arrays
Console.WriteLine(a.SequenceEqual(b));  // True: same items, same order

SequenceEqual comes from LINQ and compares item by item.

Printing an array directly gives you its type name rather than its contents: Console.WriteLine(a) prints System.Int32[]. Join the items into one string instead:

C#
Console.WriteLine(string.Join(", ", a));     // 1, 2, 3
Console.WriteLine($"[{string.Join(", ", a)}]");  // [1, 2, 3]

To fill an existing array with the same value, use Array.Fill(arr, 7) rather than writing a loop.

C# Collections Syntax

Array syntax

int[] a = new int[3];
int[] b = { 1, 2, 3 };
int[] c = [4, 5, 6];
a[0] = 10;   int last = b[^1];   int[] part = b[..2];
foreach (int x in b) { }
Array.Sort(b);   Array.Reverse(b);   Array.IndexOf(b, 2);
int[] copy = b.ToArray();
int[,] grid = new int[2, 3];   grid[0, 2] = 1;
int[][] jagged = { new[] { 1 }, new[] { 2, 3 } };

C# Collections Summary

  • Arrays hold a fixed number of items of one type; Length gives the count.
  • Indexes start at 0; ^1 is the last item; a..b is a range excluding b.
  • New arrays are filled with default values such as 0, false and null.
  • Array.Sort, Array.Reverse, IndexOf and LINQ methods work on arrays.
  • Assigning an array copies the reference, not the items; use Clone or ToArray to copy.

C# Collections Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Monthly sales

C#
decimal[] sales = { 1200m, 950m, 1430m, 1100m, 1610m, 990m };
string[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun" };

decimal total = 0;
int best = 0;
for (int i = 0; i < sales.Length; i++)
{
    total += sales[i];
    if (sales[i] > sales[best]) best = i;
}

Console.WriteLine($"Total: {total}");
Console.WriteLine($"Best month: {months[best]} ({sales[best]})");
Console.WriteLine($"Last month: {months[^1]} ({sales[^1]})");
Console.WriteLine($"First quarter: {string.Join(", ", months[..3])}");
Output
Total: 7280
Best month: May (1610)
Last month: Jun (990)
First quarter: Jan, Feb, Mar
Line-by-line explanation
  1. Lines 1 to 2Two arrays of the same length, where matching indexes belong together.
  2. Line 6for gives the index, which is needed to look up the month name.
  3. Line 9Remember the index of the highest value seen so far.
  4. Line 14^1 reads the last item without calculating Length - 1.
  5. Line 15..3 takes the first three items.
Example 2

Sorting and the copy trap

C#
int[] original = { 42, 7, 19, 3 };
int[] sameArray = original;
int[] realCopy = original.ToArray();

Array.Sort(original);
Console.WriteLine(string.Join(" ", original));
Console.WriteLine(string.Join(" ", sameArray));
Console.WriteLine(string.Join(" ", realCopy));

Console.WriteLine(Array.IndexOf(original, 19));
Console.WriteLine(original.Contains(5));
Console.WriteLine($"{original.Min()} {original.Max()} {original.Sum()}");
Output
3 7 19 42
3 7 19 42
42 7 19 3
2
False
3 42 71
Line-by-line explanation
  1. Line 2This copies the reference, so both names share one array.
  2. Line 3ToArray creates a separate copy of the items.
  3. Line 5Sort changes the array in place.
  4. Line 7sameArray shows the sorted order because it is the same array.
  5. Line 10After sorting, 19 is at index 2.
Example 3

A two-dimensional seating plan

C#
char[,] seats = new char[3, 4];

for (int r = 0; r < seats.GetLength(0); r++)
    for (int c = 0; c < seats.GetLength(1); c++)
        seats[r, c] = '.';

seats[0, 1] = 'X';
seats[2, 3] = 'X';
seats[1, 2] = 'X';

int taken = 0;
for (int r = 0; r < seats.GetLength(0); r++)
{
    Console.Write($"Row {r + 1}: ");
    for (int c = 0; c < seats.GetLength(1); c++)
    {
        Console.Write(seats[r, c]);
        if (seats[r, c] == 'X') taken++;
    }
    Console.WriteLine();
}
Console.WriteLine($"{taken} of {seats.Length} seats taken");
Output
Row 1: .X..
Row 2: ..X.
Row 3: ...X
3 of 12 seats taken
Line-by-line explanation
  1. Line 1A grid with 3 rows and 4 columns.
  2. Lines 3 to 5GetLength(0) is the number of rows and GetLength(1) the number of columns.
  3. Lines 7 to 9[row, column] picks one seat.
  4. Line 22Length on a 2D array counts every cell: 3 times 4 is 12.

Common C# Collections Mistakes

Using Length as the last index

Don't
int last = items[items.Length];     // IndexOutOfRangeException
Do
int last = items[^1];               // or items[items.Length - 1]

Trying to add to an array

Don't
int[] ids = { 1, 2 };
ids.Add(3);                         // error: arrays have no Add method
Do
var ids = new List<int> { 1, 2 };
ids.Add(3);

Thinking assignment copies the array

Don't
int[] backup = scores;
scores[0] = 0;                      // backup[0] is now 0 too
Do
int[] backup = scores.ToArray();

C# Collections in Real Projects

Arrays in real code

Image processing works with arrays of pixel values, games store tile maps in two-dimensional arrays, and high-performance code in .NET itself uses arrays and Span<T> slices to avoid extra memory. Many APIs accept or return arrays, such as string.Split and File.ReadAllLines, so you'll handle them even when your own code prefers lists.

C# Collections FAQ

How do I find the length of an array in C#?

Use the Length property: scores.Length. It's a property, so there are no brackets. For a two-dimensional array, Length gives the total number of cells, and GetLength(0) and GetLength(1) give the number of rows and columns.

How do I add an item to an array in C#?

You can't change an array's size after creating it. Use a List<T> when items will be added or removed, then call ToArray() if you need an array at the end. Array.Resize(ref arr, newSize) works, but it creates a new array and copies everything each time.

How do I copy an array in C#?

int[] copy = original.ToArray(); or (int[])original.Clone() both create a new array with the same items. Writing int[] copy = original; only copies the reference, so both names point to one array. For an array of objects, these copies are shallow: both arrays share the same objects.

Why does Console.WriteLine print System.Int32[] instead of my array?

Console.WriteLine calls ToString() on the array, and arrays don't override it, so you see the type name. Use string.Join(", ", array) to turn the items into one string, or loop through the array and print each item.

What is the difference between a jagged array and a 2D array?

A 2D array, int[,], is a single rectangular grid where every row has the same length, and you index it with grid[row, col]. A jagged array, int[][], is an array of separate arrays, so rows can differ in length, and you index it with rows[r][c]. Jagged arrays work with foreach and LINQ row by row, which makes them more common.

C# Collections Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the code to print the number of items.

int[] nums = { 4, 8, 15 };
Console.WriteLine(nums.);
Predict the outputeasy

What does this print?

string[] colours = { "red", "green", "blue" };
Console.WriteLine(colours[1]);
Predict the outputmedium

What does this print?

int[] a = { 1, 2, 3 };
int[] b = a;
b[0] = 99;
Console.WriteLine(a[0]);
Multiple choicemedium

What does new bool[3] contain?

Multiple choicehard

What does arr[1..^1] give for { 10, 20, 30, 40 }?

C# Collections Quiz

5 questions to check what you learned.

  1. What index does the first item of an array have?

    • 1
    • -1
    • It depends
    • 0
  2. Can an array change size after it's created?

    • Yes, with Add
    • No, its size is fixed; Array.Resize creates a new array
    • Only arrays of strings
    • Only in loops
  3. What does Array.IndexOf return when the value isn't found?

    • 0
    • null
    • An exception
    • -1
  4. What does ^1 mean as an index?

    • The first item
    • The last item
    • Index 1
    • An error
  5. How do you get the number of rows in int[,] grid?

    • grid.GetLength(0)
    • grid.Length
    • grid.Rows
    • grid[0].Length