Collections in C#
The core collection types -- List, Dictionary, HashSet -- and when to reach for each.
2 min read
Arrays have a fixed size decided at creation. Most real code needs something more flexible, which is where C#'s generic collection types come in.
List<T>: an ordered, resizable sequence
var names = new List<string> { "Ada", "Grace" };
names.Add("Alan");
names.Remove("Grace");
Console.WriteLine(names.Count); // 2
Console.WriteLine(names[0]); // "Ada"List<T> is the default choice for "a bunch of items in order" — it supports indexing, adding, removing, and resizes itself automatically. The <T> is a generic type parameter: List<string> is a list specifically of strings, and the compiler enforces that at compile time — you can't accidentally Add(42) to it.
Dictionary<TKey, TValue>: key-value lookups
var ages = new Dictionary<string, int>
{
["Ada"] = 30,
["Grace"] = 45,
};
ages["Alan"] = 25; // add or update
Console.WriteLine(ages["Ada"]); // 30
if (ages.TryGetValue("Nobody", out int age))
{
Console.WriteLine(age);
}
else
{
Console.WriteLine("Not found");
}Prefer TryGetValue over indexing (ages["Nobody"]) when a key might not exist — indexing throws a KeyNotFoundException on a miss, while TryGetValue returns false cleanly, following the same "try" pattern you saw with out parameters earlier.
HashSet<T>: unique, unordered values
var uniqueTags = new HashSet<string> { "css", "html", "css" };
Console.WriteLine(uniqueTags.Count); // 2 -- duplicate "css" collapses
uniqueTags.Add("js");
Console.WriteLine(uniqueTags.Contains("html")); // trueHashSet<T> automatically discards duplicates and gives you very fast Contains checks — reach for it whenever "does this collection contain X" matters more than order.
Arrays still have their place
int[] scores = { 90, 85, 77 };Arrays are fixed-size but slightly more memory-efficient and are what you'll see returned by some lower-level APIs. Unless you specifically need a fixed size known upfront, List<T> is the more flexible everyday choice.
Choosing a collection
Default to List<T> for an ordered sequence you'll grow or shrink. Reach for Dictionary<TKey, TValue> the moment you're looking things up by a key rather than a position. Reach for HashSet<T> when uniqueness and fast membership checks matter more than order. All three implement IEnumerable<T>, so foreach — and, as the next lesson covers, LINQ — works identically across all of them.
Test what you just learned
4 quick questions. Get all of them right to unlock the next lesson.
You can take the quiz without an account — logging in just lets your result count toward your progress.