1var scores = new List<int>();2scores.Add(70);3scores.Add(85);4scores.Add(90);5scores.Add(60);6scores.Add(95);7int second = scores[1];8var names = new Dictionary<int, string>();9names[101] = "Ali";10names[205] = "Sara";11names[342] = "Lee";12names.TryGetValue(205, out var who);13Console.WriteLine($"{second} {who}");[0]0[1]0[2]0[3]0Count0Capacity0[0]0[1]0[2]0[3]0[4]0[5]0[6]0[7]0key % 3101 % 3 = 2205 % 3 = 1342 % 3 = 0_85 Sarabucket 0emptybucket 1emptybucket 2empty7085906095101205342"Sara"85 Sara
Program.cs: the code each step runsMemory: the list's arrays and the dictionary's bucketsTokens: values and keys moving into their slots and bucketsLeft: the program. Right, at the back: the list's Count and Capacity, its first hidden array of 4 slots and the array of 8 it grows into. At the front: the hash step, the console, and the dictionary's 3 buckets. The values hop into slots; when the array is full the list makes one twice as big and copies across. Each key's remainder (key % 3) picks its bucket, and TryGetValue(205) goes straight to bucket 1. The program prints 85 Sara. The dictionary picture is simplified. In .NET 8 the table really starts with 3 buckets (a prime) and picks bucket = hash code % 3, but the pairs live in a separate entries array that the buckets point into, and keys that land in the same bucket are chained together. A 4th key here would grow the table to the next prime size (7).

Collections

  1. A collection keeps many values under one name. .NET has ready-made ones in System.Collections.Generic. This program uses the two you will use most: List<T>, values in order, and Dictionary<TKey, TValue>, values found by a key.

List<T>: an array that grows

Dictionary: a hash table

What happens

// step 1/11 · collections
List<T>                    values in order, read by position (index)
Dictionary<TKey, TValue>   values found by a key
both live in System.Collections.Generic
(console projects import it for you: implicit usings)

The numbers 4 and "twice as big" come from the .NET 8 source of List<T> (an empty list starts with no array, the first Add makes 4 slots, then each growth doubles). The documentation only promises that the list reallocates and copies when Count reaches Capacity, so treat the exact sizes as an implementation detail. If you know the size up front, new List<int>(1000) allocates once. The dictionary picture is simplified. In .NET 8 the table really starts with 3 buckets (a prime) and picks bucket = hash code % 3, but the pairs live in a separate entries array that the buckets point into, and keys that land in the same bucket are chained together. A 4th key here would grow the table to the next prime size (7).