Implementing custom LinkedList in C#: Best practices for Node and List classes. ungureanu
00:01 01 Jun 2026

I am currently learning data structures and decided to implement my own singly linked list in C#. I have created two separate classes: Node (representing the elements) and MyLinkedList (managing the list operations like Add, Push, and Pop).

However, I want to make sure my implementation follows C# best practices and handles edge cases correctly.

Here is my Node class implementation:

csharp:

namespace Verkettete_Liste
{
    internal class Node
    {
        // _name is just an example but this could be any object
        private string _name;
        private Node _next = null;

        public Node(string name)
        {
            _name = name;
        }

        public Node Next
        {
            get
            {
                return _next;
            }
            set
            {
                _next = value;
            }
        }

        public override string ToString()
        {
            return _name;
        }
    }
}

And here is my MyLinkedList class implementation:

csharp:

using System;

namespace Verkettete_Liste
{
    internal class MyLinkedList
    {
        private Node _head = null;

        public void Add(string name)
        {
            if (_head == null)
            {
                _head = new Node(name);
            }
            else
            {
                Node temp = _head;
                // this is where I iterate through the intire list
                while (temp.Next != null)
                {
                    temp = temp.Next;
                }
                temp.Next = new Node(name);
            }
        }

        public void Push(string name)
        {
            if (_head == null)
            {
                _head = new Node(name);
            }
            else
            {
                Node temp = _head;
                _head = new Node(name);
                _head.Next = temp;
            }
        }

        public Node Pop()
        {
            Node temp = null;
            if (_head == null)
            {
                Console.WriteLine("Noch kein Element in der Liste");
            }
            else
            {
                temp = _head;
                _head = _head.Next;
            }
            return temp;
        }

        public override string ToString()
        {
            string s = string.Empty;
            if (_head != null)
            {
                Node temp = _head;

                while (temp.Next != null)
                {
                    s += temp.Next.ToString();
                    temp = temp.Next;
                }
            }
            else
            {
                s = "Liste ist leer";
            }
            return s;
        }
    }
}

I have a few specific questions regarding this code:

  1. Memory & Performance: In MyLinkedList.Add, I always iterate through the entire list to append an element. Is it better to maintain a _tail pointer to achieve \(O(1)\) efficiency?

  2. String Concatenation: In ToString(), I use a standard while loop with string concatenation (s += ...). Is ist worth to replace this with StringBuilder to avoid performance bottlenecks with larger lists?

  3. Encapsulation: My Pop() method returns the Node object itself, exposing internal structural properties (Next) to the outside world. Is it better practice to only return the string (the name)?

  4. Code Duplication: In Push(), my if (_head == null) block does exactly the same thing as the else block would do if temp was null. Can this logic be simplified to fewer lines?

  5. C# Conventions: Are the properties, backing fields, and null-initializations aligned with modern C# standards?

Any feedback or optimization tips would be highly appreciated!

c# linked-list