# Choosing a Collection — C#/.NET

Source: https://www.skillbyai.com/en/dotnet/l-collections

> Pick the right collection type and use collection expressions.

## Different shapes for different jobs

**Arrays** (`int[]`) have a fixed length and fast indexed access. **`List<T>`** is a growable array: fast index and append, slow inserts in the middle. **`Dictionary<TKey, TValue>`** maps keys to values with near constant-time lookup; use `TryGetValue` instead of checking then indexing. **`HashSet<T>`** stores unique items with fast `Contains`. **`Queue<T>`** (first in, first out), **`Stack<T>`** (last in, first out) and **`PriorityQueue<TElement, TPriority>`** serve algorithms and schedulers. **`LinkedList<T>`** is rarely the right answer. For values that must not change, return **`IReadOnlyList<T>`** or use the immutable collections (`ImmutableList<T>`) or the read-optimised **`FrozenDictionary`** and **`FrozenSet`**. **Collection expressions** (C# 12) create most collections with one syntax: `int[] a = [1, 2, 3];`, `List<string> names = [];`, and the spread element `..` combines sequences.

## Collections by access pattern

Pick by how you read and write: by position, by key, by uniqueness or by order of arrival.

![Four small diagrams: a row of numbered slots, a set of key-to-box arrows, a circle of unique dots, and a line of items entering one end and leaving the other.](assets/figures/dotnet/section-5-map.svg) — Figure 5.1 — Lists, dictionaries, sets and queues.

## Collections in everyday code

Collection expressions work for arrays, lists, spans and more.

```cs
int[] marks = [72, 45, 90];
List<string> cities = ["Pune", "Delhi"];
List<string> more = [.. cities, "Chennai"];     // spread

var stock = new Dictionary<string, int> { ["pen"] = 120, ["notebook"] = 40 };
if (stock.TryGetValue("pen", out int pens)) Console.WriteLine(pens);
stock["eraser"] = 15;                          // add or overwrite

var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
Console.WriteLine(seen.Add("Asha"));  // True
Console.WriteLine(seen.Add("ASHA"));  // False: duplicate ignoring case

var tasks = new PriorityQueue<string, int>();
tasks.Enqueue("reply to email", 3);
tasks.Enqueue("fix prod bug", 1);
Console.WriteLine(tasks.Dequeue());   // fix prod bug
```

## Contains on a List is a linear scan

`list.Contains(x)` checks every element. Inside a loop over another large list that becomes quadratic. Put the lookup values in a `HashSet<T>` first.

**Quiz:** You need to check thousands of times whether an ID has been seen. Which collection fits best?

- [x] HashSet<T>
- [ ] List<T>
- [ ] Queue<T>
- [ ] LinkedList<T>

*Answer:* HashSet<T>. HashSet<T> offers near constant-time membership checks.
