Data Structures and Algorithms (DSA)  

C# Tip: Use Stack<T>, Not List<T>

When working with collections in C#, it’s tempting to use a List for everything. After all, it’s flexible, efficient, and familiar.

But when your use case revolves around pushing and popping elements (Last-In, First-Out behavior), Stack is the better choice.

The Common Misuse of List<T>

Many developers implement stack-like behavior with a List :

var list = new List<int>();
// Push
list.Add(10);
list.Add(20);
// Peek             
int value = list[^1];
// Pop
list.RemoveAt(list.Count - 1);

It works, but it’s not optimal:

  • You’re relying on RemoveAt, which isn’t semantically clear.

  • There’s more room for mistakes (like forgetting to use the last index).

  • List is optimized for random access, not stack-like behavior.

A better example if we have the following code

var value = list[^1];          
list.RemoveAt(list.Count - 1);    

If you accidentally do list.RemoveAt(0) , you just killed the wrong element (and it’s O(n) because it shifts the entire array).

The element at List[0] is discarded. But now, everything after it must shift left by one to fill the gap

Before: [ A, B, C, D ]
RemoveAt(0)
After:  [ B, C, D, _ ]

The Right Tool Stack<T>

What is a stack?

A Stack in C# is a Last-In, First-Out (LIFO) collection.
Think of it like a stack of plates:

  • You add a plate on top (push)

  • You look at the top plate (Peek)

  • You remove the top plate (Pop)

The last item you put in is the first one that comes out.

var stack = new Stack<int>();
// Push
tack.Push(10);   
stack.Push(20);   
// Peek
int value = stack.Peek(); 
// Pop
stack.Pop();      

Time Complexity of Operations

  • Push → O(1)
    Adds an item on top of the stack.

  • Peek → O(1)
    Reads the top item without removing it.

  • Pop → O(1)
    Removes the top item.

All these are O(1) operations, unlike List<T> where removing at the wrong index can be O(n) because of shifting.