Arrays
Learn how to declare, initialize, and work with single and multi-dimensional arrays in C#.
Declaring Arrays
An array is a fixed-size collection of elements, all of the same type, stored contiguously and efficiently in memory — this is why accessing any element by index is extremely fast, regardless of the array's size.
int[] numbers = { 10, 20, 30, 40, 50 }; // collection initializer syntaxstring[] names = new string[3]; // fixed size 3, all elements null initiallyint[] scores = new int[5]; // fixed size 5, all elements default to 0Every array in C# actually derives from the built-in System.Array class, which is why every array — regardless of its element type — automatically has properties like .Length and methods like .Sort() available.
Accessing Elements
Arrays are zero-indexed — the first element is at index 0, and the last element is at index Length - 1, not Length itself (a very common off-by-one trap covered in the mistakes section below).
int[] numbers = { 10, 20, 30 };Console.WriteLine(numbers[0]); // 10 — first elementConsole.WriteLine(numbers[2]); // 30 — last element (index 2, since Length is 3)Console.WriteLine(numbers.Length); // 3
numbers[1] = 99; // arrays are mutable — you can reassign an elementConsole.WriteLine(numbers[1]); // 99Iterating Over Arrays
Both foreach (simpler, safer) and a classic for loop with an index (needed when you must know the position) work for arrays.
int[] scores = { 88, 92, 76 };
foreach (int score in scores){ Console.WriteLine(score);}
// Using an index when position matters:for (int i = 0; i < scores.Length; i++){ Console.WriteLine($"Score {i + 1}: {scores[i]}");}Useful Array Class Methods
The static Array class (and instance methods on arrays themselves) provide several ready-made operations you'll use constantly, saving you from writing your own sorting or searching logic.
| Method | Purpose |
|---|---|
| Array.Sort(arr) | Sorts the array in place, in ascending order |
| Array.Reverse(arr) | Reverses the order of elements in place |
| Array.IndexOf(arr, value) | Returns the index of the first match, or -1 if not found |
| Array.Exists(arr, predicate) | Returns true if any element matches a given condition |
| Array.Copy(source, dest, length) | Copies elements from one array into another |
int[] numbers = { 5, 2, 8, 1, 9 };
Array.Sort(numbers);Console.WriteLine(string.Join(", ", numbers)); // 1, 2, 5, 8, 9
Array.Reverse(numbers);Console.WriteLine(string.Join(", ", numbers)); // 9, 8, 5, 2, 1
int index = Array.IndexOf(numbers, 5);Console.WriteLine(index); // 2Multi-Dimensional Arrays
C# supports true multi-dimensional arrays (declared using commas inside the brackets) for genuinely grid-shaped data, where every row has the same fixed number of columns.
int[,] grid = new int[2, 3]{ { 1, 2, 3 }, { 4, 5, 6 }};Console.WriteLine(grid[1, 2]); // 6 — row 1, column 2
// Iterating a 2D array:for (int row = 0; row < grid.GetLength(0); row++){ for (int col = 0; col < grid.GetLength(1); col++) { Console.Write($"{grid[row, col]} "); } Console.WriteLine();}A 2D array's .Length property gives the TOTAL number of elements (rows × columns combined), not the size of one dimension — use .GetLength(0) for the row count and .GetLength(1) for the column count.
Jagged Arrays
A jagged array is an array of arrays, where each inner array can have a different length — genuinely useful for data that isn't naturally grid-shaped, like a list of students each with a different number of test scores.
int[][] jagged = new int[3][];jagged[0] = new int[] { 1, 2, 3 };jagged[1] = new int[] { 4, 5 }; // a different length!jagged[2] = new int[] { 6, 7, 8, 9 };
foreach (int[] row in jagged){ Console.WriteLine(string.Join(", ", row));}Click Run to see what this code prints.
Arrays Are Reference Types
As covered in the data types lesson, arrays are reference types — assigning one array variable to another copies the reference, not the data, meaning both variables end up pointing at the exact same underlying array.
int[] original = { 1, 2, 3 };int[] alias = original; // NOT a copy — same underlying arrayalias[0] = 99;Console.WriteLine(original[0]); // 99 — original is affected too!
// To get an actual independent copy:int[] realCopy = (int[])original.Clone();realCopy[0] = 0;Console.WriteLine(original[0]); // still 99 — unaffected this timeCommon Beginner Mistakes
int[] arr = { 1, 2, 3 };Console.WriteLine(arr[3]); // throws IndexOutOfRangeException — valid indices are 0, 1, 2Arrays have a fixed size for their entire lifetime — use a `List<T>` (covered in the Collections lesson) if you need a collection that can grow or shrink.
int[] copy = original; shares the same underlying data — use .Clone() (for a shallow copy) if you need a genuinely independent array.
.Length on a 2D array returns the total element count across all dimensions, not one dimension's size — use .GetLength(0)/.GetLength(1) for row/column counts specifically.
FAQs
Not directly with a typed array like `int[]` — every element must be the same type, enforced at compile time. An `object[]` can hold anything, but you lose type safety and need to cast values back out.
A multi-dimensional array (int[,]) is one single rectangular block where every row has the same length; a jagged array (int[][]) is an array of separate, independently-sized arrays.
Not a single built-in method, but Enumerable.Repeat(value, count).ToArray() (from LINQ, covered later in this course) achieves it concisely.
No — C# arrays are always zero-indexed, with no exceptions, unlike some languages (or spreadsheet software) that use 1-based indexing.
Key Takeaways
- Arrays store a fixed number of same-typed elements, zero-indexed, with .Length giving the element count.
- The Array class provides ready-made Sort, Reverse, and IndexOf methods, among others.
- Multi-dimensional arrays (int[,]) are rectangular; jagged arrays (int[][]) allow independently-sized rows.
- Arrays are reference types — assignment shares the same data; use .Clone() for an independent copy.
- For growable collections, use List<T> instead — covered in the Collections lesson.
Summary
Arrays are the foundational way to store multiple related values in C#, and understanding their fixed size and reference semantics prevents a whole category of subtle bugs. Next, you'll go deep on strings — one of the most frequently used types in any real program.