An array is the most basic data structure that stores values of the same type arranged in a fixed size. C# supports both one-dimensional and two-dimensional arrays, and modern tools such as static methods of the Array class and Span<T> allow you to handle a variety of tasks efficiently.
Learning Objectives
- Declare and initialize a one-dimensional array and access it by index.
- Create a two-dimensional array (
int[,]) and find the size withGetLength - Use static methods such as
Array.Sort,IndexOf,Reverse, andCopy - Understand in one sentence what
Span<T>/ReadOnlySpan<T>is and why it is needed
Key concepts
1) Array declarations and collection expressions
In .NET 8, initialization can be done concisely with the collection expression [...] .
int[] a = [1, 2, 3, 4, 5]; //Collection expressions (.NET 8+)
int[] b = { 1, 2, 3 }; //traditional way
int[] c = new int[5]; //array of length 5 filled with 0
- The index starts from 0, and the last index is
Length - 1. ^1is the first from the end (=Length - 1).
2) Two-dimensional arrays
int[,] grid = new int[3, 4]; //3 rows 4 columns
grid[1, 2] = 99;
int rows = grid.GetLength(0); // 3
int cols = grid.GetLength(1); // 4
int[][] is a jagged array, so the length of each row may vary. int[,] is a rectangular array.
3) Array helper methods
| method | Description |
|---|---|
Array.Sort(arr) |
Sort ascending (in place) |
Array.Reverse(arr) |
Flip order |
Array.IndexOf(arr, value) |
First appearance index, if not present -1 |
Array.Copy(src, dst, length) |
Copy length from the front |
4) Span<T> and Memory<T>
Span<T> is a thin wrapper that points to some sections of an array/string without copying them. It is advantageous for memory and speed as it does not create a new array.
ReadOnlySpan<char> slice = "hello".AsSpan(1, 3); // "ell"
For now, all you need to remember is “efficient slicing.” Detailed usage is postponed to advanced topics.
See as example
Example 1 — ArrayBasics: Basics of one-dimensional arrays
int[] scores = [85, 92, 78, 90, 88];
Console.WriteLine($"Length: {scores.Length}");
Console.WriteLine($"First: {scores[0]}");
Console.WriteLine($"Last: {scores[^1]}");
int sum = 0;
foreach (int s in scores)
{
sum += s;
}
Console.WriteLine($"Sum: {sum}");
Execution result
Length: 5
First: 85
Last: 88
Total: 433
Note: ^1 is the "first from the end" index. This is the index operator introduced in C# 8.
Example 2 — Array2D: Handling two-dimensional arrays
int[,] grid = new int[3, 4];
for (int r = 0; r < grid.GetLength(0); r++)
{
for (int c = 0; c < grid.GetLength(1); c++)
{
grid[r, c] = r * 10 + c;
}
}
for (int r = 0; r < grid.GetLength(0); r++)
{
for (int c = 0; c < grid.GetLength(1); c++)
{
Console.Write($"{grid[r, c],3} ");
}
Console.WriteLine();
}
Execution result
0 1 2 3
10 11 12 13
20 21 22 23
Note: GetLength(0) is the number of rows, GetLength(1) is the number of columns. {value,3} is a right-aligned format with a width of 3 spaces.
Example 3 — ArrayMethods : Array static method
int[] nums = [4, 2, 9, 1, 7];
Array.Sort(nums);
Console.WriteLine($"Sort: [{string.Join(", ", nums)}]");
Array.Reverse(nums);
Console.WriteLine($"Reverse order: [{string.Join(", ", nums)}]");
int idx = Array.IndexOf(nums, 7);
Console.WriteLine($"Position of 7: {idx}");
int[] copy = new int[3];
Array.Copy(nums, copy, 3);
Console.WriteLine($"Copy the first 3: [{string.Join(", ", copy)}]");
Execution result
Sort: [1, 2, 4, 7, 9]
Reverse order: [9, 7, 4, 2, 1]
Position of 7: 1
Copy the first 3: [9, 7, 4]
Note: Array.Sort replaces the original in place (no return value). You can print the array nicely with string.Join.
Example 4 — Slicing SpanIntro : ReadOnlySpan<char>
ReadOnlySpan<char> text = "Hello, World!".AsSpan();
ReadOnlySpan<char> hello = text.Slice(0, 5);
ReadOnlySpan<char> world = text.Slice(7, 5);
Console.WriteLine(hello.ToString());
Console.WriteLine(world.ToString());
//Unlike Substring, it does not create a new string but points to the original.
Console.WriteLine($"Original length: {text.Length}, slice length: {hello.Length}");
Execution result
Hello
World
Original Length: 13, Slice Length: 5
Note: string.Substring allocates a new string each time, while Span shares memory. Useful in bulk text parsing.
Common Mistakes
- Access the last + 1 index like
arr[arr.Length]→IndexOutOfRangeException. - Access the two-dimensional array as
grid[1][2]—int[,]is correct asgrid[1, 2]. (grid[1][2]is forint[][]). - The illusion that
Array.Sortreturns a new array — replace the original (void). - The size of
int[]cannot be increased once it is set — if a variable length is needed, useList<T>in the next section. Span<T>cannot be carried beyondawaitof an asynchronous method — note that its use is limited.
Cleanup
- The array is a same type, fixed length data structure and is made concise with the collection expression
[1, 2, 3]. - For a two-dimensional array, find the size as
int[,],GetLength(0/1). - Frequently used operations are solved with the
Arraystatic method (Sort,IndexOf,Reverse,Copy). Span<T>is a modern tool for pointing parts without copying.
Try it yourself
cd src/ArrayBasics
dotnet run
cd ../Array2D
dotnet run
cd ../ArrayMethods
dotnet run
cd ../SpanIntro
dotnet run