This stack implementation stores items in a linked list. Additionally, the program shows how to copy a stack:

using System;

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

            string input = "one two three - - four five - six";

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

            Console.WriteLine("\n{0} items left on the stack.", s.Size);

            Console.WriteLine("\nCreate a new stack and add a few items to it:");
            Stack a = new Stack();
            a.Push("X");
            a.Push("Y");
            a.Push("Z");
            a.ShowItems();

            Console.WriteLine("\nCopy the stack:");
            Stack r = new Stack(a);

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

            // We can push and pop from either a or r without influencing the each other.
            Console.WriteLine("\nPush W to the original.");
            a.Push("W");
            Console.WriteLine("Pop {0} from the copy.\n", r.Pop());

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

            Console.ReadKey();
        }

        class Stack where T : class
        {
            private Node first; // the top of stack (most recently added node)
            private int N; // stack 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; } }

            public Stack() { }

            // This constructor makes a new and independent copy of the given stack.
            public Stack(Stack s)
            {
                Stack c = new Stack(); // the copy of the stack 's' in reverse order

                int size = s.Size;

                // Copy s to c in reverse order.
                for (int i = 0; i < size; ++i)
                {
                    T item = s.Pop();
                    c.Push(item); // add the element to c
                }

                // Copy c to 'this' and to s.
                // Because items in c are in reverese order, they will be in correct order in 'this' and s.
                for (int i = 0; i < size; ++i)
                {
                    T item = c.Pop();
                    Push(item); // add the element to 'this' stack
                    s.Push(item); // re-add the element to s
                }
            }

            public void Push(T item)
            {
                // Add item to the top of stack i.e., insert the item at the beginning of the linked list.
                Node oldFirst = first;
                first = new Node();
                first.Item = item;
                first.Next = oldFirst;

                ++N;
            }

            public T Pop()
            {
                // Remove item from the top of stack i.e., remove the item from the beginning of the linked list.
                // Note that the NullReferenceException is thrown if the Pop method is called on an empty stack.
                T item = first.Item;
                first = first.Next;

                --N;

                return item;
            }

            public void ShowItems()
            {
                for (Node node = first; node != null; node = node.Next)
                {
                    Console.Write("{0} ", node.Item.ToString());
                }
                Console.WriteLine();
            }

            private class Node
            {
                public T Item { get; set; }
                public Node Next { get; set; }

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