C# (.NET 8 LTS) track

Lesson 11 · Part 3: Collections & LINQ

Arrays

Store fixed-size data in one- and two-dimensional arrays and use Span and Memory for slices.

Part 3: Collections & LINQ4 min readFree lesson

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 with GetLength
  • Use static methods such as Array.Sort, IndexOf, Reverse, and Copy
  • 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.
  • ^1 is 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

  1. Access the last + 1 index like arr[arr.Length] → IndexOutOfRangeException.
  2. Access the two-dimensional array as grid[1][2] — int[,] is correct as grid[1, 2]. (grid[1][2] is for int[][]).
  3. The illusion that Array.Sort returns a new array — replace the original (void).
  4. The size of int[] cannot be increased once it is set — if a variable length is needed, use List<T> in the next section.
  5. Span<T> cannot be carried beyond await of 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 Array static 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

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/Array2D/Array2D.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Coll11</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
src/Array2D/Program.csC#
#nullable enable

//3 rows 4 columns rectangular array
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;
    }
}

//Output in table format
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();
}
src/ArrayBasics/ArrayBasics.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Coll11</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
src/ArrayBasics/Program.csC#
#nullable enable

//Create an array as a collection (.NET 8+)
int[] scores = [85, 92, 78, 90, 88];

Console.WriteLine($"Length: {scores.Length}");
Console.WriteLine($"First: {scores[0]}");
Console.WriteLine($"Last: {scores[^1]}");   //1st from the end

int sum = 0;
foreach (int s in scores)
{
    sum += s;
}
Console.WriteLine($"Sum: {sum}");
src/ArrayMethods/ArrayMethods.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Coll11</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
src/ArrayMethods/Program.csC#
#nullable enable

int[] nums = [4, 2, 9, 1, 7];

Array.Sort(nums);                  //Sort in place
Console.WriteLine($"Sort: [{string.Join(", ", nums)}]");

Array.Reverse(nums);               //Flip the order
Console.WriteLine($"Reverse order: [{string.Join(", ", nums)}]");

int idx = Array.IndexOf(nums, 7);  //Find the location of a value
Console.WriteLine($"Position of 7: {idx}");

int[] copy = new int[3];
Array.Copy(nums, copy, 3);         //Copy the first 3
Console.WriteLine($"Copy the first 3: [{string.Join(", ", copy)}]");
src/SpanIntro/Program.csC#
#nullable enable

ReadOnlySpan<char> text = "Hello, World!".AsSpan();

//Points to part of the original without creating a new string
ReadOnlySpan<char> hello = text.Slice(0, 5);
ReadOnlySpan<char> world = text.Slice(7, 5);

Console.WriteLine(hello.ToString());
Console.WriteLine(world.ToString());

Console.WriteLine($"Original length: {text.Length}, slice length: {hello.Length}");
src/SpanIntro/SpanIntro.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Coll11</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Assignment

Problem 1 — Maximum, Minimum, Average

  • Reference solution: shown below
  • Key concepts: one-dimensional array, foreach, cumulative calculation

Requirements

  • Use int[] data = [42, 17, 89, 23, 65, 8, 50];.
  • Iterates through the array and directly calculates and outputs the maximum value, minimum value, and average. (Math.Max / Math.Min available)
  • The average is output to the first decimal place (F1).

Expected output

Array: [42, 17, 89, 23, 65, 8, 50]
Maximum: 89
Minimum: 8
Average: 42.0

Hint

  • It is neat to set the initial value as data[0] and compare starting from index 1.
  • The average is (double)sum / data.Length — Cast double to avoid integer division.

Problem 2 — 2D matrix transpose

  • Reference solution: shown below
  • Key concepts: int[,], GetLength, double for statement

Requirements

  • Create the following 2x3 matrix.
    1 2 3
    4 5 6
    
  • Transpose and output as a 3x2 matrix.
  • Both the original and transposed results are output in table format.

Expected output

Original (2x3):
1 2 3
4 5 6

Transpose (3x2):
1 4
2 5
3 6

Hint

  • The transposed array is created with new int[original.GetLength(1), original.GetLength(0)].
  • transposed[c, r] = original[r, c]; is the key line.

Check the correct answer

After solving it yourself, compare it with the reference solution below.

Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

Homework01/Homework01.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Coll11</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
Homework01/Program.csC#
#nullable enable

int[] data = [42, 17, 89, 23, 65, 8, 50];

int max = data[0];
int min = data[0];
int sum = 0;

foreach (int n in data)
{
    max = Math.Max(max, n);
    min = Math.Min(min, n);
    sum += n;
}

double avg = (double)sum / data.Length;

Console.WriteLine($"Array: [{string.Join(", ", data)}]");
Console.WriteLine($"Maximum value: {max}");
Console.WriteLine($"Minimum: {min}");
Console.WriteLine($"average: {avg:F1}");
Homework02/Homework02.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Coll11</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
Homework02/Program.csC#
#nullable enable

int[,] original = { { 1, 2, 3 }, { 4, 5, 6 } };

int rows = original.GetLength(0);
int cols = original.GetLength(1);

int[,] transposed = new int[cols, rows];
for (int r = 0; r < rows; r++)
{
    for (int c = 0; c < cols; c++)
    {
        transposed[c, r] = original[r, c];
    }
}

Print("Original (2x3):", original);
Console.WriteLine();
Print("Transpose (3x2):", transposed);

static void Print(string title, int[,] m)
{
    Console.WriteLine(title);
    for (int r = 0; r < m.GetLength(0); r++)
    {
        for (int c = 0; c < m.GetLength(1); c++)
        {
            Console.Write($"{m[r, c]} ");
        }
        Console.WriteLine();
    }
}

Learn this lesson with a mentor

Work through the C# (.NET 8 LTS) track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now