Codectionary / Developer documentation / C#

LinkedList<T>

LinkedList<T> is a doubly-linked list implementation from System.Collections.Generic. Unlike List<T>, it stores elements as individual nodes linked to their neighbors, which makes inserting and removing elements at the beginning, end, or middle (given a reference to the node) very fast, at the cost of slower access by index, since reaching a specific position means walking the chain.

Read the syntax

LinkedList<T> connects nodes. AddFirst and AddLast insert at the ends; a known LinkedListNode<T> can be used for efficient nearby insertion or removal.

Find searches for a value and can return null. Removing by value must search, so it is not generally constant-time; RemoveFirst is constant-time for a nonempty list.

Syntax

LinkedList<Type> list = new LinkedList<Type>();

Examples

Basic LinkedList Usage

Adding elements to the front and back of a LinkedList<T>.

LinkedList<string> tasks = new LinkedList<string>();
tasks.AddLast("Write code");
tasks.AddLast("Test code");
tasks.AddFirst("Plan project");  // fast - O(1), unlike List<T>.Insert(0, ...)

foreach (string task in tasks)
{
    Console.WriteLine(task);
}
  1. Adding elements to the front and back of a LinkedList<T>.
  2. LinkedList<T> connects nodes. AddFirst and AddLast insert at the ends; a known LinkedListNode<T> can be used for efficient nearby insertion or removal.
  3. AddFirst puts Plan project ahead of the two tasks appended by AddLast. foreach prints the resulting order.

Working with Nodes

LinkedList<T> exposes its nodes directly, allowing efficient insertion relative to a known position.

LinkedList<int> numbers = new LinkedList<int>();
numbers.AddLast(1);
numbers.AddLast(3);

LinkedListNode<int> node = numbers.Find(1);
numbers.AddAfter(node!, 2);  // insert between 1 and 3

Console.WriteLine(string.Join(", ", numbers));  // 1, 2, 3
  1. LinkedList<T> exposes its nodes directly, allowing efficient insertion relative to a known position.
  2. LinkedList<T> connects nodes. AddFirst and AddLast insert at the ends; a known LinkedListNode<T> can be used for efficient nearby insertion or removal.
  3. Find locates the node containing 1, and AddAfter inserts 2 before 3. The output becomes 1, 2, 3; check Find for null in real input.

Removing Elements

Removing from either end is constant-time; removing by value must first search for the matching node.

LinkedList<string> queue = new LinkedList<string>();
queue.AddLast("first");
queue.AddLast("second");
queue.AddLast("third");

queue.RemoveFirst();
Console.WriteLine(string.Join(", ", queue));  // second, third

queue.Remove("third");
Console.WriteLine(string.Join(", ", queue));  // second
  1. Removing from either end is constant-time; removing by value must first search for the matching node.
  2. LinkedList<T> connects nodes. AddFirst and AddLast insert at the ends; a known LinkedListNode<T> can be used for efficient nearby insertion or removal.
  3. RemoveFirst drops first and the initial print shows second, third. Removing the value third leaves only second.

Best practices

  • Choose LinkedList<T> over List<T> when your code frequently inserts or removes elements at the beginning, end, or a known middle position
  • Choose List<T> instead when you mostly need fast random access by index - LinkedList<T> access by index is slow since it must walk the chain
  • Use AddFirst()/AddLast()/AddBefore()/AddAfter() with a known node reference to get the real performance benefit LinkedList<T> offers
  • For simple stack or queue behavior specifically, prefer the dedicated Stack<T>/Queue<T> types over LinkedList<T> - they are simpler and just as efficient

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading