Day 6: Arrays and Collections - Boxes Inside Bigger Boxes
arrow_back All Posts
April 06, 2026 6 min read .NET/C#

Day 6: Arrays and Collections - Boxes Inside Bigger Boxes

Welcome back! Yesterday you learned how to make your code repeat itself with loops. But loops are only fun when you have stuff to loop over. Today we give your program the ability to hold not just one value, but a whole pile of them. Welcome to arrays and collections — the cardboard boxes that hold other cardboard boxes.

1. The Problem With Individual Variables

Let's say you need to store the names of 5 students. Without collections, you'd do this:

string student1 = "Alice";
string student2 = "Bob";
string student3 = "Charlie";
string student4 = "Diana";
string student5 = "Eve";

Now imagine 500 students. You'd need 500 variables. Your fingers would fall off, your code would be unreadable, and you'd seriously reconsider your career choices. Arrays fix this.

2. Arrays — The Fixed-Size Shelf

An array is a container that holds a fixed number of values, all of the same type. Think of it as a shelf with numbered slots.

string[] students = ["Alice", "Bob", "Charlie", "Diana", "Eve"];

That's a collection expression (the [ ] syntax) — the modern C# 12+ way to create arrays. Five strings, one line. The compiler figures out the size for you.

To access an element, use its index (the slot number):

Console.WriteLine(students[0]);  // Alice
Console.WriteLine(students[2]);  // Charlie
Console.WriteLine(students[4]);  // Eve

Indices start at 0, not 1. The first element is [0], the last is [length - 1]. This is the same reason for loops start at 0 — it all connects.

What happens if you go out of bounds?

Console.WriteLine(students[5]);  // BOOM: IndexOutOfRangeException

The array has 5 elements (indices 0–4). Asking for index 5 is like opening a drawer that doesn't exist — C# throws an IndexOutOfRangeException and your program crashes. This is arguably the most common beginner bug in all of programming.

3. Looping Through Arrays

Remember foreach from Day 5? This is where it shines:

string[] fruits = ["Apple", "Banana", "Cherry"];

foreach (string fruit in fruits)
{
    Console.WriteLine($"I like {fruit}!");
}

Or with a for loop when you need the index:

for (int i = 0; i < fruits.Length; i++)
{
    Console.WriteLine($"Fruit #{i}: {fruits[i]}");
}

.Length gives you the number of elements. Always use it instead of hardcoding the count — that way if the array changes, your loop doesn't break.

4. Lists — The Stretchy Array

Arrays have one big limitation: you can't change their size after creation. Need to add a 6th student? Too bad, you'd have to create a whole new array.

Enter List<T> — a collection that grows and shrinks as needed:

List<string> names = ["Alice", "Bob", "Charlie"];

names.Add("Diana");           // now 4 items
names.Add("Eve");             // now 5 items
names.Remove("Bob");          // now 4 items (Bob is gone)

Console.WriteLine(names.Count);  // 4

The <string> part is a generic type parameter — it tells the list what type of items it holds. List<int> holds integers, List<bool> holds booleans, etc. The compiler enforces this, so you can't accidentally sneak a number into a List<string>.

Key differences from arrays:

Feature Array (T[]) List (List<T>)
Size Fixed at creation Grows and shrinks
Add/remove elements No Yes
Performance Slightly faster Slightly more overhead
Element count .Length .Count
When to use Size is known Size may change

Rule of thumb: if you don't know how many items you'll have, use List<T>. When in doubt, use List<T>. Seriously, List<T> is what you'll use 90% of the time in real code.

5. Useful List Methods

List<T> comes with a bunch of handy methods:

List<int> scores = [85, 92, 78, 95, 88];

scores.Add(100);              // add to the end
scores.Insert(0, 70);         // insert at index 0
scores.Remove(78);            // remove first occurrence of 78
scores.RemoveAt(2);           // remove element at index 2
scores.Sort();                // sort in ascending order
scores.Reverse();             // reverse the order
scores.Clear();               // remove everything

bool has95 = scores.Contains(95);  // true (before Clear!)
int idx = scores.IndexOf(92);      // returns the index, or -1 if not found

You don't need to memorize all of these right now. Just know they exist — when you think "I wish I could sort this list," the method is already there.

For the full reference, see the List<T> docs.

6. Dictionaries — The Lookup Table

Sometimes you don't want a list of things — you want to look up a value by a key, like a real dictionary (word → definition).

Dictionary<string, int> ages = new()
{
    ["Alice"] = 25,
    ["Bob"] = 30,
    ["Charlie"] = 28
};

Console.WriteLine(ages["Alice"]);   // 25

ages["Diana"] = 22;                 // add a new entry
ages["Bob"] = 31;                   // update Bob's age

Console.WriteLine(ages.Count);      // 4

Dictionary<string, int> means: keys are string, values are int. Every key must be unique — adding a duplicate key with Add() would throw an exception (but assigning with ages["Alice"] = ... just overwrites the value).

Looping through a dictionary:

foreach (var pair in ages)
{
    Console.WriteLine($"{pair.Key} is {pair.Value} years old");
}

Each element is a KeyValuePair with .Key and .Value properties. Dictionaries are unordered — don't assume they'll come out in the order you put them in.

7. When to Use What

Collection Use when
T[] (array) Fixed size, known at compile time, max speed
List<T> Need to add/remove items (most common choice)
Dictionary<TKey, TValue> Need fast lookup by a unique key

There are more collection types in C# (HashSet<T>, Queue<T>, Stack<T>, LinkedList<T>), but these three cover the vast majority of beginner scenarios. We'll meet the others as we need them.

8. Your Homework: Student Grade Tracker

Build a console app that lets the user enter student names and scores, stores them in a dictionary, and then prints a summary.

Dictionary<string, int> grades = [];

while (true)
{
    Console.Write("Student name (or 'done' to finish): ");
    string name = Console.ReadLine() ?? "";

    if (name == "done") break;

    Console.Write("Score: ");
    int score = int.Parse(Console.ReadLine() ?? "0");

    grades[name] = score;
}

Console.WriteLine("\n--- Grade Report ---");
foreach (var entry in grades)
{
    string letterGrade = entry.Value switch
    {
        >= 90 => "A",
        >= 80 => "B",
        >= 70 => "C",
        >= 60 => "D",
        _ => "F"
    };
    Console.WriteLine($"{entry.Key}: {entry.Value} ({letterGrade})");
}

Look at that — you're using a while (true) loop with break (Day 5), a switch expression (Day 4), string interpolation (Day 2), and a dictionary (today). It's all connecting.

Bonus challenge: after the grade report, print the class average using a foreach loop to sum all scores and divide by grades.Count.

Summary of Day 6

  • Arrays (T[]) hold a fixed number of same-type elements. Index starts at 0.
  • List<T> is a resizable array — use it when you need to add or remove items. This is your go-to collection.
  • Dictionary<TKey, TValue> maps unique keys to values — perfect for lookups.
  • Use .Length for arrays, .Count for lists and dictionaries.
  • IndexOutOfRangeException is what you get for asking for an element that doesn't exist. Respect the bounds.
  • Collection expressions ([ ]) are the modern way to initialize arrays and lists in C# 12+.

Tomorrow: we'll talk about Methods — how to break your code into reusable, named chunks instead of writing one giant wall of code in Main. Your programs are about to get organized. 🧩

See you on Day 7!

Share
FM

Farhad Mammadov

.NET Engineer & Cloud Architect · Bayern, Germany. Writing about scalable backend systems, AWS, and SRE.