Skip to content

Chapter 11: Arrays - Storing Fixed Sequences of Data (Vectors)

Theoretical Foundations

In the previous chapter, we learned how to repeat actions using loops. We used a counter variable to keep track of our position in the iteration. This worked well for simple tasks, but as we build more complex programs—especially in AI applications—we often need to store and manipulate large sets of data simultaneously. Imagine trying to build a simple sentiment analysis tool. You might have a list of 100 customer reviews. You cannot store review #1 in a variable named review1, review #2 in review2, and so on. That would be unmanageable. You need a way to store all 100 reviews in a single, organized container.

This is where Arrays come in. An array is a fixed-size container that holds multiple values of the same type. In C#, arrays are fundamental building blocks for handling data sequences.

The Real-World Analogy: The Egg Carton

Think of an array like an egg carton. An egg carton has a fixed number of slots (usually 12). You cannot force a 13th egg into a standard carton without breaking the structure.

  1. Fixed Size: Once you buy the carton, the number of slots is set.
  2. Same Type: Every slot holds an egg. You don't put a tomato in one slot and a battery in another.
  3. Order: The slots are numbered (0 to 11). You can say, "Give me the egg in slot 3."

In C#, an array works exactly like this. It holds a fixed number of variables of the same type, arranged in a sequence.

How Arrays Fit into the C# Type System

In Chapter 2, we learned about specific types like int, double, and string. An array is also a type, but it is a reference type. This is a crucial concept from the C# type system.

  • Value Types (Stack): int, double, bool. These store the actual data. When you assign one to another, you copy the data.
  • Reference Types (Heap): string, array, and (later) classes. These store a reference (like an address) to where the data lives in memory.

When you create an array, you are creating an object on the "Heap" (a large pool of memory). The variable you use to hold the array actually holds the address pointing to that data.

Declaring and Initializing Arrays

To use an array, you must tell C# two things: what type of data it will hold and how many slots it needs.

1. Syntax

The syntax uses square brackets []. The number inside the brackets defines the size.

// Declaring an array of integers with a size of 5
int[] scores = new int[5];
  • int[]: This is the type. It reads as "array of int".
  • scores: The name of the variable.
  • new int[5]: This creates the actual array in memory. new allocates the space, and [5] sets the fixed size (the egg carton size).

2. Default Values

When you create an array of numbers, C# automatically fills the slots with the default value of that type (0 for int, 0.0 for double, false for bool).

using System;

class Program
{
    static void Main()
    {
        // Create an array of 5 integers
        int[] numbers = new int[5];

        // Access the first slot (index 0)
        Console.WriteLine(numbers[0]); // Output: 0
    }
}

3. Array Initialization

You can also declare and fill the array in one step using a comma-separated list inside curly braces {}. This is often called "collection initialization."

// Declares an array of strings with 3 elements
string[] names = { "Alice", "Bob", "Charlie" };

Note on Size: When using the curly brace syntax, you do not specify the number inside the brackets. C# counts the items inside the braces and sets the size automatically.

// Correct
string[] names = new string[3] { "Alice", "Bob", "Charlie" };

// Also Correct (size inferred)
string[] names = new string[] { "Alice", "Bob", "Charlie" };

// Also Correct (simplest form)
string[] names = { "Alice", "Bob", "Charlie" };

Accessing and Modifying Data: Zero-Based Indexing

In Chapter 9, we used for loops to count iterations starting from 0. This aligns perfectly with how arrays work. C# arrays are zero-indexed, meaning the first element is at index 0, the second at index 1, and the last at index length - 1.

If you try to access an index equal to or greater than the size of the array, C# will crash with an IndexOutOfRangeException. This is the program equivalent of trying to grab an egg from a slot that doesn't exist.

int[] scores = new int[3]; // Indices: 0, 1, 2

scores[0] = 100; // First element
scores[1] = 95;
scores[2] = 80;

// scores[3] = 50; // CRASH! Index 3 is out of range.

The Length Property

Every array has a built-in property called Length. This tells you the fixed size of the array. This is incredibly useful for loops, ensuring you never go out of bounds.

string[] students = { "John", "Sarah", "Mike" };
Console.WriteLine(students.Length); // Output: 3

Iterating Over Arrays

Since we know how to use for loops (Chapter 9) and arrays, we can combine them to process every element in the array. This is the standard way to handle data sequences.

Example: Processing an Array of Doubles

Imagine we are building a simple AI recommendation system that calculates the average rating of 5 movies.

using System;

class Program
{
    static void Main()
    {
        // 1. Initialize the array with fixed ratings
        double[] ratings = { 4.5, 5.0, 3.5, 2.0, 4.0 };

        // 2. Use a variable to hold the sum (Chapter 2)
        double sum = 0.0;

        // 3. Iterate using a for loop (Chapter 9)
        // We use ratings.Length to get the exact size
        for (int i = 0; i < ratings.Length; i++)
        {
            // Access the element at the current index
            sum = sum + ratings[i];

            // Visualizing the process
            Console.WriteLine($"Processing index {i}, rating: {ratings[i]}");
        }

        // 4. Calculate average (Arithmetic from Chapter 4)
        double average = sum / ratings.Length;

        Console.WriteLine("Average Rating: " + average);
    }
}

Why this matters for AI: In machine learning, data often comes in vectors (arrays of numbers). We rarely process data points one by one manually; we use loops to feed these arrays into mathematical formulas (like calculating the average, finding the max, or normalizing data).

Multi-Dimensional Arrays (Matrices)

Sometimes, data isn't just a single line; it's a grid. C# supports multi-dimensional arrays. The most common is a 2D array, which is like a spreadsheet or a matrix. This is essential for image processing or storing weights in a neural network.

Syntax for 2D Arrays

You use a comma inside the brackets to define dimensions.

// A 2D array: 2 rows, 3 columns
int[,] matrix = new int[2, 3];

You can visualize this as a grid:

A 2D array in C# is visualized as a grid with rows and columns, defined using commas in the brackets (e.g., int[2, 3]), which is essential for organizing data like image pixels or neural network weights.
Hold "Ctrl" to enable pan & zoom

A 2D array in C# is visualized as a grid with rows and columns, defined using commas in the brackets (e.g., `int[2, 3]`), which is essential for organizing data like image pixels or neural network weights.

Initializing a 2D Array

You use nested curly braces. The outer braces represent rows, and the inner braces represent columns.

int[,] gameBoard = {
    { 1, 0, 1 }, // Row 0
    { 0, 1, 0 }  // Row 1
};

Iterating a 2D Array

To visit every cell in a 2D array, you need a nested loop (Chapter 10). The outer loop handles the rows, and the inner loop handles the columns.

using System;

class Program
{
    static void Main()
    {
        // A simple 2x2 grid representing pixel brightness (0-255)
        int[,] imageData = {
            { 255, 0 },
            { 128, 255 }
        };

        // Outer loop iterates through rows (0 to 1)
        for (int row = 0; row < 2; row++)
        {
            // Inner loop iterates through columns (0 to 1)
            for (int col = 0; col < 2; col++)
            {
                Console.Write(imageData[row, col] + " ");
            }
            Console.WriteLine(); // Move to next line after printing a row
        }
    }
}

Jagged Arrays (Arrays of Arrays)

There is another type called a "jagged array." This is an array where each element is itself an array of potentially different lengths. Think of it as a carton where the first row holds 3 eggs, the second row holds 5, and the third holds 2. While possible in C#, it is less common in strict matrix math but useful for variable-length lists.

// Declare a jagged array
int[][] jagged = new int[3][]; // 3 rows, variable columns

jagged[0] = new int[] { 1, 2 }; // Row 0 has 2 elements
jagged[1] = new int[] { 3, 4, 5, 6 }; // Row 1 has 4 elements
jagged[2] = new int[] { 7 }; // Row 2 has 1 element

Practical Application: Arrays in AI Logic

Let's look at a concrete example of how arrays are used in the logic of a simple AI algorithm: Binary Classification.

Imagine we are building a spam filter. We have a list of words, and we assign a "spam score" to each word. If the total score of an email exceeds a threshold, it's marked as spam.

  1. Data Storage: We store the scores in an array.
  2. Processing: We iterate through the array to sum the scores.
  3. Decision: We use an if statement (Chapter 6) to make a decision.
using System;

class Program
{
    static void Main()
    {
        // 1. Store data: Scores for words found in an email
        // "Free" = 5 points, "Money" = 3 points, "Urgent" = 4 points
        int[] wordScores = { 5, 3, 4, 2, 5 }; 

        // 2. Process: Sum the scores (using a for loop)
        int totalScore = 0;

        for (int i = 0; i < wordScores.Length; i++)
        {
            totalScore = totalScore + wordScores[i];
        }

        // 3. Decision: Logic from Chapter 6
        int spamThreshold = 10;

        if (totalScore > spamThreshold)
        {
            Console.WriteLine($"Spam detected! Score: {totalScore}");
        }
        else
        {
            Console.WriteLine($"Email is safe. Score: {totalScore}");
        }
    }
}

Summary of Key Concepts

  1. Fixed Size: Arrays are static. Once created, their size cannot change (unlike future dynamic collections). This makes them memory-efficient and fast.
  2. Homogeneous Data: All elements in an array must be of the same type (int[], string[], etc.).
  3. Zero-Based Indexing: Access starts at 0. The last index is Length - 1.
  4. System.Array: Under the hood, every array inherits from System.Array. This gives them the .Length property and allows them to be used in various contexts, though we don't access the base class directly yet.
  5. Multi-Dimensional Arrays: Use , to create grids (matrices) for complex data structures like images or game boards.

Arrays are the foundation of data storage in C#. Mastering them allows you to handle collections of data efficiently, which is the first step toward building algorithms that can learn and make decisions.

Basic Code Example

Here is a simple, 'Hello World' level code example for arrays.

Real-World Context: The Exam Score Tracker

Imagine you are a teacher who has just graded a pop quiz for a small group of 5 students. You want to record their scores and calculate the class average. Since the number of students is fixed (5), an array is the perfect tool to store this sequence of data.

Code Example: Storing and Processing Exam Scores

using System;

class Program
{
    static void Main()
    {
        // 1. Declare an array to hold 5 integer scores.
        // We use 'int[]' to specify an array of integers.
        // The number '5' sets the fixed size of the array.
        int[] scores = new int[5];

        // 2. Assign individual scores using the array index.
        // Array indices start at 0 and go up to (size - 1).
        // This is like putting numbers into specific numbered boxes.
        scores[0] = 85;
        scores[1] = 92;
        scores[2] = 78;
        scores[3] = 95;
        scores[4] = 88;

        // 3. Calculate the total score.
        // We use a 'for' loop to visit every index from 0 to 4.
        // We add the score at the current index to our running total.
        int total = 0;
        for (int i = 0; i < 5; i++)
        {
            total = total + scores[i];
        }

        // 4. Calculate the average.
        // We divide the total by the number of items (5).
        // We cast the total to a double to ensure we get a decimal result.
        double average = (double)total / 5;

        // 5. Display the results.
        Console.WriteLine($"Total Score: {total}");
        Console.WriteLine($"Class Average: {average}");
    }
}

Step-by-Step Explanation

  1. Declaration (int[] scores): We declare a variable named scores. The syntax int[] tells C# that this variable will hold a sequence of integers. It does not create the array yet; it just prepares a slot for it.

  2. Initialization (new int[5]): The new keyword actually creates the array in memory. The number inside the brackets [5] defines the fixed size. This allocates space for exactly 5 integers. Once created, this size cannot be changed. The indices are automatically numbered 0, 1, 2, 3, and 4.

  3. Assignment (scores[0] = 85): We access specific positions in the array using square brackets [] containing the index number. This is called indexing. We place the first score (85) into index 0, the second (92) into index 1, and so on.

  4. Iteration (for (int i = 0; i < 5; i++)): To process the data, we use a for loop. The loop initializes a counter i at 0. It continues running as long as i is less than 5. In every cycle, it adds scores[i] to the total variable. The loop increments i by 1 after each cycle, ensuring we visit every element in the array.

  5. Calculation ((double)total / 5): We perform arithmetic to find the average. Because total is an int and 5 is an int, standard integer division would truncate the decimal part. By casting total to a double using (double), we force the calculation to use floating-point math, preserving the decimal precision of the average.

Visualizing the Array

The array scores looks like this in memory:

A diagram would show an array of integer scores (e.g., 85, 92, 78) being summed into a variable total, which is then cast to a double to perform floating-point division, resulting in a precise decimal average rather than a truncated integer.
Hold "Ctrl" to enable pan & zoom

A diagram would show an array of integer scores (e.g., 85, 92, 78) being summed into a variable `total`, which is then cast to a `double` to perform floating-point division, resulting in a precise decimal average rather than a truncated integer.

Common Pitfalls

1. IndexOutOfRangeException The most common error when using arrays is trying to access an index that doesn't exist. Remember that array indices start at 0. If you declare an array of size 5, the valid indices are 0 through 4.

  • Incorrect: scores[5] = 100; (This will crash the program because index 5 is out of bounds).
  • Correct: scores[4] = 100; (This is the last valid slot).

2. Forgetting to Initialize Declaring an array (int[] scores;) does not create it. You must use new int[size] to allocate memory. If you try to assign values to scores[i] without initializing it first, the compiler will give you an error stating the array might be null.

3. Off-by-One Errors in Loops When writing a for loop to iterate through an array, the condition must be i < array.Length (or i < 5 in this example). If you use i <= 5, the loop will attempt to access index 5 on the final iteration, causing an exception.

The chapter continues with advanced code, exercises and solutions with analysis, you can find them on the ebook on Leanpub.com or Amazon



Code License: All code examples are released under the MIT License. Github repo.

Content Copyright: Copyright © 2026 Edgar Milvus | Privacy & Cookie Policy. All rights reserved.

All textual explanations, original diagrams, and illustrations are the intellectual property of the author. To support the maintenance of this site via AdSense, please read this content exclusively online. Copying, redistribution, or reproduction is strictly prohibited.