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]:

C#
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]);
Output
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:

C#
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}");
}
Output
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:

C#
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 '-';
}
Output
 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:

C#
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));
}
Output
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

C#
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)}");
Output
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 lengthsAll the sameCan differ
Accessa[r, c]a[r][c]
SizeGetLength(0), GetLength(1)a.Length, a[r].Length
Rows as valuesNoYes — each row is an ordinary array you can pass around
Works with LINQAwkwardNaturally

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:

C#
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]);
Output
3
504
21.7

Try it yourself

Transpose a matrix — swap its rows and columns — then print both.

Try it yourself · Program.cs
Edit the code, copy it into Program.cs and run it with dotnet run Program.cs (.NET 10 or later). How to set up .NET
Output
  1  2  3
  4  5  6

  1  4
  2  5
  3  6