Implementing Linked List in C#
Getting a solid grasp on how data structures work in C# is critical for your success. Building a linked list from scratch is a great place to start as it will help you understand how this data structure works under the hood. I’ve always found linked lists fascinating because they’re simple yet powerful, offering a dynamic way to store and manage data. In this write-up, I’ll walk you through how to implement a singly linked list in C#, and we’ll cover some common operations—like adding nodes, removing nodes, and searching for values. I’ll keep it practical and straightforward, with code you can use and tweak as you need.
For your convenience, I have a public GitHub repo with this code and some tests for it available here. You can use it to tinker with so that you don’t have to start from scratch, but I do highly recommend typing it out yourself as it is helpful for learning.
What’s a Linked List?
Picture a chain where each link connects to the next one. That’s a linked list in a nutshell. Unlike an array, where elements sit side by side in memory, a linked list is made up of nodes, each holding a value and a reference (or “link”) to the next node. This structure makes it super flexible—you can add or remove items without shifting everything around, which is a hassle with typical arrays.
In a singly linked list, each node only points forward to the next node. That’s what we’ll build here. It starts with a head (the first node), and the last node points to null to mark the end.
Why Use a Linked List?
Before we jump into the code, let’s talk about why you’d want to use a linked list:
Dynamic Size – You can keep adding nodes as long as memory allows, no need to set a size upfront like with arrays.
Efficient Inserts and Deletes – Adding or removing nodes is quick if you know where to do it, without shifting other elements.
Foundation for Learning – It’s a stepping stone to more complex structures like stacks, queues, or even doubly linked lists.
Sure, it’s not perfect—it’s slower to access elements by index since you have to traverse the list—but for certain tasks, it’s a fantastic tool.
Implementing a Linked List in C#
Let’s build a singly linked list step by step. We’ll start with a Node class to represent each link, then create a LinkedList class to manage them.
Step 1: The Node Class
Each node needs two things: the data it holds and a reference to the next node.
public class Node
{
public int Data { get; set; } // The value stored in the node
public Node Next { get; set; } // The link to the next node
public Node(int data)
{
Data = data;
Next = null; // By default, it points to nothing
}
}I’m using int for simplicity, but you could make this generic with <T> if you want to store any type—something to try later!
Step 2: The LinkedList Class
Now, let’s create the LinkedList class. It’ll track the head of the list and provide methods for common operations.
public class LinkedList
{
private Node head; // The first node in the list
// We’ll add methods here soon!
}The head is our entry point. If it’s null, the list is empty. Simple, right?
Common Operations and How to Write Them
Here’s where the fun begins—let’s add some methods to make this list useful. I’ll walk you through each one with code and explain what’s happening.
1. Add a Node to the End (Append)
Let’s say you want to add a new value to the end of the list. You’ll need to traverse to the last node and link the new one there.
public void Append(int data)
{
Node newNode = new Node(data);
if (head == null) // If the list is empty
{
head = newNode; // The new node becomes the head
return;
}
Node current = head;
while (current.Next != null) // Traverse to the end
{
current = current.Next;
}
current.Next = newNode; // Link the new node
}How it works: If the list is empty, the new node becomes the head. Otherwise, you walk through the list until you hit a node with no Next, then attach the new node there. I’ve used this a ton—it’s great for building lists incrementally.
2. Add a Node to the Start (Prepend)
We can also add a node directly at the beginning. It is even easier since you just update the head.
public void Prepend(int data)
{
Node newNode = new Node(data);
newNode.Next = head; // Point the new node to the current head
head = newNode; // Make the new node the new head
}How it works: The new node takes the old head as its Next, then becomes the head itself. This is fast—no traversal needed!
3. Remove a Node by Value
Let’s remove a node with a specific value. You’ll need to find it and adjust the links around it.
public void Remove(int data)
{
if (head == null) // Empty list, nothing to do
return;
if (head.Data == data) // If the head is the target
{
head = head.Next; // Move head to the next node
return;
}
Node current = head;
while (current.Next != null && current.Next.Data != data)
{
current = current.Next; // Move forward until you find it
}
if (current.Next != null) // If we found the value
{
current.Next = current.Next.Next; // Skip over the node to remove
}
}How it works: If the head matches, you just shift it forward. Otherwise, you scan the list, and when you find the node, you link its predecessor to its successor. If the value isn’t there, nothing happens—safe and simple.
4. Search for a Value
Wondering if a value exists in the list? Let’s add a method to check.
public bool Contains(int data)
{
Node current = head;
while (current != null)
{
if (current.Data == data)
return true; // Found it!
current = current.Next;
}
return false; // Not here
}How it works: You start at the head and check each node. If you find the value, you’re golden; if you hit null, it’s not in the list. I’ve used this to debug or validate data plenty of times.
5. Print the List
To see what’s in your list, let’s add a method to display it.
public void Print()
{
Node current = head;
while (current != null)
{
Console.Write(current.Data + " -> ");
current = current.Next;
}
Console.WriteLine("null");
}How it works: Traverse the list and print each value, ending with “null” to show the end. It’s a handy way to peek at your list’s state.
Putting It All Together
Here’s the full LinkedList class with all the methods we’ve built:
public class LinkedList
{
private Node head;
public void Append(int data)
{
Node newNode = new Node(data);
if (head == null)
{
head = newNode;
return;
}
Node current = head;
while (current.Next != null)
{
current = current.Next;
}
current.Next = newNode;
}
public void Prepend(int data)
{
Node newNode = new Node(data);
newNode.Next = head;
head = newNode;
}
public void Remove(int data)
{
if (head == null)
return;
if (head.Data == data)
{
head = head.Next;
return;
}
Node current = head;
while (current.Next != null && current.Next.Data != data)
{
current = current.Next;
}
if (current.Next != null)
{
current.Next = current.Next.Next;
}
}
public bool Contains(int data)
{
Node current = head;
while (current != null)
{
if (current.Data == data)
return true;
current = current.Next;
}
return false;
}
public void Print()
{
Node current = head;
while (current != null)
{
Console.Write(current.Data + " -> ");
current = current.Next;
}
Console.WriteLine("null");
}
}And here’s how you can test it:
class Program
{
static void Main()
{
LinkedList list = new LinkedList();
list.Append(1);
list.Append(2);
list.Prepend(0);
list.Print(); // Output: 0 -> 1 -> 2 -> null
list.Remove(1);
list.Print(); // Output: 0 -> 2 -> null
Console.WriteLine(list.Contains(2)); // True
Console.WriteLine(list.Contains(1)); // False
}
}What’s Next?
You’ve got a working linked list now—nice work! If you’re up for more, here are a few ideas to try:
Make it Generic – Swap int for <T> so you can store anything.
Add More Operations – Try inserting at a specific position or counting nodes.
Go Doubly Linked – Add a Previous reference for two-way traversal.
Building this from scratch is a great way to improve your data structures knowledge! Linked lists are a frequently used structure so you’ll want to be sure to understand this one thoroughly. It is a small project, but it opens the door to developing your data structures skills even further and tackling new challenges!

