LinkedList
Intro
LinkedList<T> is a doubly linked list where each node points to previous and next nodes. It is useful when you already keep node references and need frequent O(1) inserts/removes around those nodes.
Unlike array-backed collections, linked lists do not store elements contiguously:
- Random index access is O(n) because traversal is required.
- Inserting/removing at a known node is O(1).
- Each element carries node-pointer overhead, so memory locality is worse than
List<T>.
Structure
graph LR
H[head] --> N1[node a]
N1 <--> N2[node b]
N2 <--> N3[node c]
N3 --> T[tail]Example
var list = new LinkedList<string>();
var a = list.AddLast("A");
list.AddLast("C");
list.AddAfter(a, "B");
list.Remove("C");
Pitfalls
- Using
LinkedList<T>for index-based access causes O(n) scans and can underperformList<T>significantly. PreferList<T>/arrays for index-heavy workloads, or store node handles when linked-list locality edits are truly required. - Using detached or foreign
LinkedListNode<T>instances as anchors (AddBefore,AddAfter,Remove) throws because a node must belong to the target list context. Checknode.Listbefore using node handles and re-find/re-add nodes when needed. - Pointer-rich node allocation hurts cache locality, so iteration can be slower even when complexity looks similar on paper. Prefer
List<T>for traversal-heavy workloads unless node-local O(1) edits are the dominant operation.
Tradeoffs
LinkedList<T>vsList<T>: linked list wins for O(1) local edits around known nodes; list usually wins for traversal and random access.LinkedList<T>vsQueue<T>/Stack<T>: queue/stack APIs are simpler and often faster when you only need FIFO/LIFO behavior.
Questions
Why is
LinkedList<T> often slower than List<T> in real workloads despite O(1) inserts/removes?
CPU cache locality dominates many workloads. List<T> keeps data contiguous, while linked-list nodes are scattered and require pointer chasing.
When is
LinkedList<T> the right choice in .NET?
When your algorithm already stores LinkedListNode<T> handles and performs many localized inserts/removes around them.
What is a common migration signal from
LinkedList<T> to List<T>?
If code frequently searches by index/value before each operation, you are paying O(n) traversal repeatedly and should usually switch to List<T> or another structure.
Links
LinkedList<T>class — API reference covering node operations, AddBefore/AddAfter, and enumeration.- Selecting a collection class — Microsoft decision guide; explains when linked list is appropriate vs array-backed collections.
- Performance tips for collections — overview of .NET collection types with complexity and memory characteristics.
- Exploring C# LinkedLists via LRU Caches — practitioner example of a real use case (LRU cache) where O(1) node-local edits justify linked list overhead.