Skip to main content
C# Fundamentals for Beginners to Advanced
CHAPTER 20 Beginner

Generics and Collections in C#

Updated: May 17, 2026
5 min read

# CHAPTER 20

Generics and Collections

1. Introduction

In Chapter 9, we learned about List<T>. Have you ever wondered what the <T> means? It stands for Type. It is a feature called Generics. Generics allow you to design classes and methods where the data type is a variable to be specified later. This is what enables a single List class to hold ints, strings, or custom Player objects without rewriting the class!

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the concept of Generics (<T>).
  • Write your own Generic Methods and Classes.
  • Use Dictionary<TKey, TValue> for key-value pairs.
  • Use Queue<T> (First-In, First-Out).
  • Use Stack<T> (Last-In, First-Out).

3. Generic Methods

Imagine writing a method that swaps two integers. Then you need to swap two strings. Without generics, you have to write two overloaded methods. With generics, you write it *once*.
csharp
1234567891011121314151617181920212223
using System;

class Program
{
    // <T> acts as a placeholder for the data type
    static void Swap<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }

    static void Main()
    {
        int x = 5, y = 10;
        Swap<int>(ref x, ref y); // Passing integers

        string s1 = "Hello", s2 = "World";
        Swap<string>(ref s1, ref s2); // Passing strings!
        
        Console.WriteLine($"{s1} {s2}"); // Prints "World Hello"
    }
}

4. Generic Classes

Just like methods, entire classes can be generic. This is exactly how Microsoft built List<T>.
csharp
12345678910111213141516171819202122232425262728
class Box<T>
{
    private T _content;

    public void AddContent(T item)
    {
        _content = item;
    }

    public T GetContent()
    {
        return _content;
    }
}

class Program
{
    static void Main()
    {
        // A box that holds an int
        Box<int> intBox = new Box<int>();
        intBox.AddContent(123);

        // A box that holds a string
        Box<string> stringBox = new Box<string>();
        stringBox.AddContent("Secret Document");
    }
}

5. Advanced Collections: Dictionary<TKey, TValue>

A dictionary stores data in Key-Value pairs. It is incredibly fast for looking up data (like a real-world dictionary). *(Requires using System.Collections.Generic;)*
csharp
12345678910111213141516
using System.Collections.Generic;

Dictionary<string, int> ages = new Dictionary<string, int>();

// Adding Key-Value pairs
ages.Add("Alice", 25);
ages.Add("Bob", 30);

// Looking up a value by its Key (Very Fast!)
Console.WriteLine($"Bob is {ages["Bob"]} years old.");

// Iterating through a Dictionary
foreach (KeyValuePair<string, int> pair in ages)
{
    Console.WriteLine($"{pair.Key} : {pair.Value}");
}

6. Advanced Collections: Queue<T>

A Queue operates on the FIFO (First-In, First-Out) principle. Think of a line at a grocery store. The first person in line is the first person served.
csharp
123456
Queue<string> line = new Queue<string>();

line.Enqueue("Alice"); // Joins the line
line.Enqueue("Bob");

string served = line.Dequeue(); // Removes and returns the first person ("Alice")

7. Advanced Collections: Stack<T>

A Stack operates on the LIFO (Last-In, First-Out) principle. Think of a stack of plates. The last plate you put on top is the first one you take off. (This is exactly how the call stack manages memory!).
csharp
1234567
Stack<string> browserHistory = new Stack<string>();

browserHistory.Push("google.com");
browserHistory.Push("github.com");

// Removes and returns the top item ("github.com")
string lastVisited = browserHistory.Pop(); 

8. Common Mistakes

  • Accessing a missing Dictionary key: If you ask for ages["Charlie"] but "Charlie" isn't in the dictionary, the program will crash. Always check first using if (ages.ContainsKey("Charlie")).
  • Using non-generic collections: Avoid ArrayList and Hashtable. Always use their modern generic equivalents: List<T> and Dictionary<TKey, TValue> to ensure type safety.

9. Best Practices

  • Use constraints to limit generics if necessary. E.g., class MathOperation<T> where T : struct ensures T can only be a value type (like a number), preventing someone from doing math on strings.

10. Exercises

  1. 1. Create a Dictionary<int, string> to map employee IDs (Key) to employee names (Value). Add 3 employees and print one out by looking up their ID.
  1. 2. Create a generic class Storage<T> that holds an array of 3 items of type T.

11. MCQs with Answers

Question 1

What does the <T> syntax signify in C#?

Question 2

What is the primary benefit of Generics?

Question 3

Which collection stores data in Key-Value pairs?

Question 4

What happens if you try to retrieve a key from a Dictionary that does not exist?

Question 5

A Queue<T> operates on which principle?

Question 6

Which method adds an item to a Queue?

Question 7

A Stack<T> operates on which principle?

Question 8

Which method removes and returns the top item from a Stack?

Question 9

Which generic collection is the modern, type-safe replacement for the old Hashtable?

Q10. Can you restrict a generic class to only accept reference types? a) Yes, using the where T : class constraint b) No, generics must accept all types Answer: a) Yes, using the where T : class constraint

12. Interview Questions

  • Q: What is the difference between List<T> and Dictionary<TKey, TValue>? When would you use one over the other?
  • Q: Explain the difference between Queue and Stack. Provide a real-world use case for each in software development (e.g., Undo functionality vs. Task scheduling).
  • Q: Why are Generics more performant than using object references (Boxing/Unboxing)?

13. Summary

Generics <T> empower you to write flexible, reusable code that works across multiple data types while maintaining strict type safety. Combining this with powerful structures like Dictionary, Queue, and Stack allows you to solve complex data management problems efficiently.

14. Next Chapter Recommendation

What if you have a List of 1,000 users and you want to find all users older than 18, sorted by name? Doing this manually takes a lot of loops. In Chapter 21: LINQ in C#, we will learn how to query collections effortlessly using SQL-like syntax.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·