This queue implementation stores items in a linked list. Additionally, the program shows how to make a new and independent copy of the given queue:

using System;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Queue q = new Queue();

            string input = "A B C D - E - - F - - - G";

            foreach (string item in input.Split(" ".ToCharArray()))
            {
                if (item.Equals("-") && !q.IsEmpty)
                    Console.Write(q.Dequeue() + " ");
                else
                    q.Enqueue(item);
            }

            Console.WriteLine("\n{0} item(s) left in the queue.\n", q.Size);

            Console.WriteLine("Add a few items to the queue:");
            q.Enqueue("X");
            q.Enqueue("Y");
            q.Enqueue("Z");
            q.ShowItems();

            Console.WriteLine("Copy the queue:\n");
            Queue r = new Queue(q);

            Console.Write("Orig: ");
            q.ShowItems();
            Console.Write("Copy: ");
            r.ShowItems();

            // We can enqueue and dequeue from either q or r without influencing the other.
            Console.WriteLine("Enqueue W to the original.");
            q.Enqueue("W");
            Console.WriteLine("Dequeue {0} from the copy.\n", r.Dequeue());

            Console.Write("Orig: ");
            q.ShowItems();
            Console.Write("Copy: ");
            r.ShowItems();

            Console.ReadKey();
        }

        class Queue
        {
            private Node first; // link to least recently added node
            private Node last;  // link to most recently added node
            private int N;      // queue size (the number of items in the linked list)

            public bool IsEmpty { get { return first == null; } } // the same as N == 0
            public int Size { get { return N; } }

            // Default ctor.
            public Queue() { }

            // 1.3.41 p.169 - Makes a copy of the given queue.
            public Queue(Queue q)
            {
                int size = q.Size;

                // Delete all of the nodes from q and add these nodes to both q and 'this'.
                for (int i = 0; i < size; ++i)
                {
                    T item = q.Dequeue();
                    Enqueue(item); // add the element to 'this' queue
                    q.Enqueue(item); // re-add the element to q
                }
            }

            public void Enqueue(T item)
            {
                // Add item to the end of the list.
                Node oldLast = last;
                last = new Node();
                last.Item = item;
                last.Next = null;

                if (IsEmpty)
                    first = last;
                else
                    oldLast.Next = last;

                ++N;
            }

            public T Dequeue()
            {
                // Remove item from the beginning of the list.
                T item = first.Item;
                first = first.Next;

                if (IsEmpty)
                    last = null;

                --N;

                return item;
            }

            // Prints all the items in the queue.
            public void ShowItems()
            {
                for (Node node = first; node != null; node = node.Next)
                {
                    Console.Write("{0} ", node.Item.ToString());
                }
                Console.WriteLine();
                Console.WriteLine("First = {0}->{1}", (first != null ? first.Item.ToString() : "null"), (first != null && first.Next != null ? first.Next.Item.ToString() : "null"));
                Console.WriteLine("Last  = {0}->{1}", (last != null ? last.Item.ToString() : "null"), (last != null && last.Next != null ? last.Next.Item.ToString() : "null")); // last.Next should always be null
                Console.WriteLine();
            }

            // Nested class to define nodes of linked list.
            private class Node
            {
                public T Item { get; set; }
                public Node Next { get; set; }

                public override string ToString() { return (Item == null ? "null" : Item.ToString()); }
            }
        }
    }
}