I recently learned the core .NET Queue type uses arrays internally, and that this is actually much more efficient. I've had a go at writing a singly-linked list version of a queue, MyQueue.

Running basic stopwatch times against this type and the .NET type shows about 50ms difference when queuing 1 million items and checking the length.

How can it be improved?

MyQueueNode

namespace MyQ.Core
{
public class MyQueueNode<T> : IMyQueueNode<T>
{
private MyQueueNode<T> _nextNode;

private T _value;

public MyQueueNode(T value)
{
_value = value;
}

public void SetNextNode(ref MyQueueNode<T> nextNode)
{
_nextNode = nextNode;
}

public MyQueueNode<T> GetNextNode()
{
return _nextNode;
}

public T GetValue()
{
return _value;
}
}
}


MyQueue

namespace MyQ.Core
{
public class MyQueue<T> : IMyQueue<T> where T : class
{

public void Enqueue(T item)
{
MyQueueNode<T> newNode = new MyQueueNode<T>(item);

{
}
else
{
_tailNode.SetNextNode(ref newNode);
_tailNode = newNode;
}

_length++;
}

public T Dequeue()
{
{
throw new QueueEmptyException();
}

_length--;

return value;
}

public T Peek()
{
{
return null;
}

}

private long _length = 0;

public long Length => _length;
}
}

• This is the complete code, I'm just quite anal about organisation and use those comments to separate methods from member fields and to group methods by functionality, like others might use #region I've removed them so there's no confusion. – Lee Mar 30 '18 at 12:09

MyQueueNode:

• where is IMyQueueNode<T>?
• _value can be made readonly
• there is no need for MyQueueNode to be public. You should restrict its access modifier as much as possible. Clients don't need to see your queue internals.
• in SetNextNode there is no need to pass argument by reference

MyQueue:

• QueueEmptyException is not defined.
• Peek method returns null on empty queue. What if there is null as data value? You might consider throwing an exception as seen in Dequeue and let user check queue by checking its length before the Peek is called.

private long _length = 0;
public long Length => _length;


you might consider comfortable using auto property (and changing references to _length):

public long Length { get; private set; }


Don't use volatile in the below line

    private volatile MyQueueNode<T> _headNode, _tailNode;

• A short explanation why it is bad to use volatile here would be better than just a link. – t3chb0t Apr 10 '18 at 18:17
• Vishnu are you suggesting I should make the _value field within the node volatile instead of the class that it's contained within? That's what I gather from the article. – Lee Apr 13 '18 at 12:53