I guess this has been made a couple of times by now, but i wanted to take my chance on creating a simple generic linked list in c#. What do you think ?
This is the main class.
public class LinkedList<T>: IEnumerator<T>
{
private Node<T> head;
private Node<T> tail;
public T Current
{
get { return myCurrentNode.GetValue(); }
}
object IEnumerator.Current => Current;
private Node<T> myCurrentNode;
public LinkedList()
{
head = null;
tail = null;
}
public void Add(T value)
{
if (head == null && tail == null)
{
head = new Node<T>(value);
tail = head;
Reset();
return;
}
tail.SetNextNode(new Node<T>(value));
tail = tail.GetNextNode();
}
public void RemoveCurrentNode()
{
var node = new Node<T>();
node.SetNextNode(head);
while (node.GetNextNode() != myCurrentNode)
{
node = node.GetNextNode();
}
var nextNode = myCurrentNode.GetNextNode();
node.SetNextNode(nextNode);
if (head == myCurrentNode)
{
head = nextNode;
}
if (tail == myCurrentNode)
{
tail = node;
}
myCurrentNode = nextNode;
}
public bool MoveNext()
{
var nextNode = myCurrentNode.GetNextNode();
if (nextNode != null)
{
myCurrentNode = nextNode;
return true;
}
return false;
}
public void Reset()
{
myCurrentNode = new Node<T>();
myCurrentNode.SetNextNode(head);
}
public void Dispose()
{
myCurrentNode = null;
head = null;
tail = null;
}
}
Node class.
public class Node<T>
{
private T _value;
private Node<T> _nextNode;
public Node()
{
}
public T GetValue()
{
return _value;
}
public Node(T Value)
{
_value = Value;
}
public Node<T> GetNextNode()
{
return _nextNode;
}
public void SetNextNode(Node<T> nextNode)
{
_nextNode = nextNode;
}
}
And three unit tests to check my implementation.
public class LinkedListTest
{
private LinkedList.LinkedList<int> linkedList;
private List<int> initialList;
[Fact]
public void LinkedListCanBeEnumerated()
{
//arange
InitializeLinkedList(100);
//act
int[] array = new int[100];
int index = 0;
while (linkedList.MoveNext())
{
array[index++] = (linkedList.Current);
}
//assert
array.ToList().ForEach(i => initialList.Contains(i).ShouldBe(true));
}
private void InitializeLinkedList(int howMany)
{
linkedList = new LinkedList.LinkedList<int>();
initialList = Enumerable.Range(1, howMany).ToList();
initialList.ForEach(i => linkedList.Add(i));
}
[Fact]
public void RemovingCurrentNodeShouldAlterTheList()
{
//arange
InitializeLinkedList(100);
//act
linkedList.MoveNext();
linkedList.RemoveCurrentNode();
linkedList.Reset();
int[] array = new int[100];
int index = 0;
while (linkedList.MoveNext())
{
array[index++] = (linkedList.Current);
}
//assert
array.ToList().ForEach(i => i.ShouldNotBe(1));
}
[Fact]
public void RemovingTailNodeShouldResultInADifferentTailNode()
{
//arange
InitializeLinkedList(3);
//act
linkedList.MoveNext();
linkedList.MoveNext();
linkedList.MoveNext();
linkedList.RemoveCurrentNode();
linkedList.Reset();
int[] array = new int[3];
int index = 0;
while (linkedList.MoveNext())
{
array[index++] = (linkedList.Current);
}
//assert
array.ToList().ForEach(i => i.ShouldNotBe(3));
}
}