Multidimensional and Jagged Arrays
Some data is naturally a grid: a game board, a spreadsheet, the pixels of an image, a seating plan. C# offers two ways to store it: rectangular arrays, where every row has the same length, and jagged arrays — arrays of arrays — where each row can have its own length.
Rectangular arrays
A comma inside the brackets adds a dimension. int[,] is a two-dimensional array, accessed with [row, column]:
int[,] grid = new int[3, 4]; // 3 rows, 4 columns, all 0 grid[0, 0] = 1; grid[2, 3] = 9; Console.WriteLine(grid.Length); // total elements Console.WriteLine(grid.Rank); // number of dimensions Console.WriteLine(grid.GetLength(0)); // rows Console.WriteLine(grid.GetLength(1)); // columns Console.WriteLine(grid[2, 3]);
12 2 3 4 9
Initialising and looping
Nested braces give the initial values, one inner block per row. Nested loops visit every cell; use GetLength for each dimension's size:
int[,] sales = { { 12, 15, 9 }, { 20, 18, 25 }, { 7, 11, 14 }, }; string[] shops = ["North", "Centre", "South"]; for (int row = 0; row < sales.GetLength(0); row++) { int rowTotal = 0; Console.Write($"{shops[row],-7}"); for (int col = 0; col < sales.GetLength(1); col++) { Console.Write($"{sales[row, col],4}"); rowTotal += sales[row, col]; } Console.WriteLine($" = {rowTotal}"); }
North 12 15 9 = 36 Centre 20 18 25 = 63 South 7 11 14 = 32
foreach also works on a rectangular array, visiting every element row by row — but you lose track of which row and column you're in.
A game board
A tic-tac-toe board is a 3×3 grid of characters. Checking for a winner means checking rows, columns and diagonals:
char[,] board = { { 'X', 'O', 'X' }, { 'O', 'X', 'O' }, { ' ', ' ', 'X' }, }; for (int r = 0; r < 3; r++) { Console.WriteLine($" {board[r, 0]} | {board[r, 1]} | {board[r, 2]}"); if (r < 2) Console.WriteLine("---+---+---"); } Console.WriteLine($"Winner: {Winner(board)}"); static char Winner(char[,] b) { for (int i = 0; i < 3; i++) { if (b[i, 0] != ' ' && b[i, 0] == b[i, 1] && b[i, 1] == b[i, 2]) return b[i, 0]; if (b[0, i] != ' ' && b[0, i] == b[1, i] && b[1, i] == b[2, i]) return b[0, i]; } if (b[1, 1] != ' ' && ((b[0, 0] == b[1, 1] && b[1, 1] == b[2, 2]) || (b[0, 2] == b[1, 1] && b[1, 1] == b[2, 0]))) return b[1, 1]; return '-'; }
X | O | X ---+---+--- O | X | O ---+---+--- | | X Winner: X
Jagged arrays
A jagged array is an array whose elements are themselves arrays: int[][]. Each inner array is created separately and can have its own length:
int[][] triangle = new int[5][]; for (int row = 0; row < triangle.Length; row++) { triangle[row] = new int[row + 1]; triangle[row][0] = triangle[row][row] = 1; for (int col = 1; col < row; col++) { triangle[row][col] = triangle[row - 1][col - 1] + triangle[row - 1][col]; } } foreach (int[] row in triangle) { Console.WriteLine(string.Join(" ", row)); }
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1
That's Pascal's triangle — each row is one longer than the last, which a rectangular array can't express without wasting space. Note the syntax: triangle[row][col], with separate brackets.
Jagged arrays with collection expressions
string[][] teams = [ ["Ana", "Ben"], ["Chen", "Dara", "Eli", "Fay"], ["Gus"], ]; for (int t = 0; t < teams.Length; t++) { Console.WriteLine($"Team {t + 1} ({teams[t].Length}): {string.Join(", ", teams[t])}"); } Console.WriteLine($"Players: {teams.Sum(team => team.Length)}");
Team 1 (2): Ana, Ben Team 2 (4): Chen, Dara, Eli, Fay Team 3 (1): Gus Players: 7
Which one to use?
Rectangular T[,] | Jagged T[][] | |
|---|---|---|
| Row lengths | All the same | Can differ |
| Access | a[r, c] | a[r][c] |
| Size | GetLength(0), GetLength(1) | a.Length, a[r].Length |
| Rows as values | No | Yes — each row is an ordinary array you can pass around |
| Works with LINQ | Awkward | Naturally |
Use rectangular arrays for true grids (boards, matrices, images). Use jagged arrays — or a List<List<T>> — when rows vary or need to be handled individually.
Three or more dimensions
Add more commas for more dimensions. A 3D array might store a value per day, hour and sensor:
double[,,] readings = new double[7, 24, 3]; readings[2, 14, 1] = 21.7; Console.WriteLine(readings.Rank); Console.WriteLine(readings.Length); Console.WriteLine(readings[2, 14, 1]);
3 504 21.7
Try it yourself
Transpose a matrix — swap its rows and columns — then print both.
1 2 3 4 5 6 1 4 2 5 3 6