A data structure organizes data for efficient access, mutation, and iteration. In .NET, the standard library provides production-ready implementations of the most common structures — List<T>, Dictionary<TKey, TValue>, HashSet<T>, Queue<T>, Stack<T>, LinkedList<T>, SortedSet<T>, and PriorityQueue<TElement, TPriority>. Choosing the right collection usually has a bigger impact on performance than micro-optimizing the code that uses it.

The key decision is matching operations to complexity guarantees: random access by index → array or List<T>; fast lookup by key → Dictionary<TKey, TValue>; membership tests → HashSet<T>; ordered traversal → SortedSet<T> or sorted array; FIFO processing → Queue<T>. Most production performance issues with collections come from using the wrong structure (for example, searching a List<T> linearly when a HashSet<T> gives expected O(1) lookups) rather than from the structure’s implementation being slow.

Choose by workload and access pattern

Start from the operation that dominates the workload, then account for ordering, memory layout, and concurrency. A structure with the right asymptotic lookup can still lose when it adds indirection to a small, scan-heavy collection.

WorkloadDefault structureWhat it buysCost or boundary
Dense positional access and iterationArray or List<T>O(1) indexing and contiguous storageMiddle insertions shift elements
Key-to-value lookupDictionary<TKey, TValue>Expected O(1) lookup by a stable keyHashing, resizing, and no sorted traversal
Membership and set algebraHashSet<T>Expected O(1) containment; linear-time set algebra over the participating inputsStores no associated value or order; collision patterns affect worst-case lookup cost
FIFO workQueue<T> or Channel<T>Preserves arrival order; channels add asynchronous coordination and backpressureNo arbitrary indexed access
Repeated minimum or maximum selectionPriorityQueue<TElement, TPriority>O(1) peek and O(log n) enqueue/dequeueIteration is not globally sorted
Ordered range queriesSorted array or balanced treeBinary search or ordered traversalUpdates are expensive in arrays; trees add pointer overhead
Prefix lookupTrieWork scales with key length rather than entry countHigh node and reference overhead
Relationships and pathsGraph adjacency listStores sparse edges without an n × n matrixTraversal needs visited-state and cycle handling
Adaptive spatial range or nearest-neighbor queriesQuadtree, R-tree, or spatial database indexPrunes regions that cannot intersect the queryChoice depends on data distribution and persistence model
Spatial candidates on a one-dimensional indexGeohashTurns fixed-grid cells into sortable prefixesAdjacent points can cross a prefix boundary; exact filtering is still required
Cheap negative membership testsBloom filterAvoids expensive downstream lookups with compact stateFalse positives are possible; deletions need a variant

The visual is an example inventory, not a selector. The table above is authoritative because the same structure can be right or wrong depending on the dominant operation and storage boundary.

Questions

References

6 items under this folder.