Skip to main content

23. Generics in C#

Level: Guided

ℹ️ What You'll Learn
  • What generics are
  • Why List<T> uses generics
  • Create a generic method
  • Create a generic class
  • Understand type safety
  • Use simple constraints

You already used generics:

List<string> names = new List<string>();
List<Student> students = new List<Student>();

The <string> and <Student> parts are generics.

The Problem: Same Logic for Different Types

We may need to print:

  • Student names
  • Teacher names
  • Subject names

Without generics, we may create many similar methods.

Generics let one method or class work with many types.

What is a Generic?

A generic uses a type placeholder.

Common placeholder is T.

static void PrintItem<T>(T item)
{
Console.WriteLine(item);
}

Call it:

PrintItem<string>("Sahasra");
PrintItem<int>(101);
PrintItem<double>(84.8);

Quick Definitions

  • Generic - Code that works with different types using placeholder T
  • Type placeholder - Variable name like T representing any type
  • Type safety - Only correct types allowed (prevents mixing strings and numbers)
  • Reusable - One method/class works for many types
  • List<T> - List that stores items of one type only
  • Dictionary<TKey,TValue> - Dictionary with key-value types specified
  • Generic method - Method with <T> like PrintList<T>
  • Generic class - Class with <T> like Repository<T>
  • Constraint - Rule like where T : IEntity
  • Type argument - Actual type like Student in Repository<Student>

Why Generics Are Useful

Generics give:

  • Reusable code
  • Type safety
  • Less casting
  • Cleaner collections

Wrong old style:

List<object> items = new List<object>();
items.Add("Sahasra");
items.Add(101);

Problem: mixed data can cause mistakes.

Better:

List<string> names = new List<string>();
names.Add("Sahasra");

Now only strings are allowed.

Generic Method

static void PrintList<T>(List<T> items)
{
foreach (T item in items)
{
Console.WriteLine(item);
}
}

Usage:

List<string> subjects = new List<string> { "Maths", "Science" };
List<int> marks = new List<int> { 80, 90, 75 };

PrintList(subjects);
PrintList(marks);

One method works for different types.

Generic Class

public class Box<T>
{
public T Value { get; set; }

public Box(T value)
{
Value = value;
}
}

Usage:

Box<string> nameBox = new Box<string>("Sahasra");
Box<int> rollBox = new Box<int>(101);

Simple Generic Repository

Repository means a class that stores and retrieves items.

💻 Try It — Console App
💡 Paste into Program.cs and press F5⌥ GitHub
Repository<Student> studentRepository = new Repository<Student>();

studentRepository.Add(new Student { Name = "Sahasra", ClassName = "10-A" });
studentRepository.Add(new Student { Name = "Priya", ClassName = "10-A" });

foreach (Student student in studentRepository.GetAll())
{
Console.WriteLine($"{student.Name} - {student.ClassName}");
}

public class Repository<T>
{
private List<T> _items = new List<T>();

public void Add(T item)
{
_items.Add(item);
}

public List<T> GetAll()
{
return _items;
}
}

public class Student
{
public string Name { get; set; } = "";
public string ClassName { get; set; } = "";
}

The same Repository<T> can work for:

Repository<Student>
Repository<Teacher>
Repository<Subject>

Generic Constraint

Sometimes T must follow a rule.

Example: only classes with Id property.

public interface IEntity
{
int Id { get; set; }
}

public class Repository<T> where T : IEntity
{
public void PrintId(T item)
{
Console.WriteLine(item.Id);
}
}

where T : IEntity means:

T must implement IEntity.

When You'll Use This in SMS

Every SMS entity needs generic repositories.

Real repositories in SMS:

Repository<Student> studentRepo; // Store students
Repository<Teacher> teacherRepo; // Store teachers
Repository<Subject> subjectRepo; // Store subjects
Repository<Exam> examRepo; // Store exams
Repository<FeeAccount> feeRepo; // Store fee accounts

Same Repository<T> code, different types.

Generic methods in SMS:

PrintList<Student>(allStudents);
PrintList<Teacher>(allTeachers);
PrintList<Exam>(allExams);

Generic constraints in SMS:

// Only entities with Id property
Repository<T> where T : IEntity

// Find by Id safely
Entity FindById<T>(int id) where T : IEntity

Real impact: Without generics = create StudentRepository, TeacherRepository, SubjectRepository separately (repetitive). With generics = one Repository<T> works for all (DRY principle).

Production SMS has 50+ generic types and methods.


Try This Now

Run the Repository example above. Then experiment:

  1. Create Repository<Teacher>
  2. Add two teachers
  3. Print all teachers
  4. Create generic method FindFirst<T> that returns first item
  5. Test with different types (Student, Teacher, Subject)

See how one generic repository works for all entity types.


ℹ️ Video Tutorial

Generics explained: List<T>, generic methods, generic classes, Repository<T>, constraints. Video coming soon. Subscribe to NexCoding YouTube for updates.


Common Mistakes

Mistake 1: Using object instead of generic

Prefer List<Student> over List<object>.

Mistake 2: Making generics too complex

Keep beginner generic classes simple.

Mistake 3: Forgetting type argument

Wrong:

Repository repo = new Repository();

Correct:

Repository<Student> repo = new Repository<Student>();

Best Practices

  1. Use generics for reusable type-safe code.
  2. Use T for simple generic type names.
  3. Use clear names like TEntity for larger code.
  4. Use constraints only when needed.
  5. Prefer List<T> and Dictionary<TKey,TValue> over object collections.

Practice Task

Create Repository<T> and use it for:

  • Student
  • Teacher

Add two objects to each repository and print them.

Quick Revision

QuestionAnswer
What is generic placeholder?T
Example of generic collection?List<Student>
Why use generics?Reusable and type-safe code
What is generic method?Method with <T>
What is constraint?Rule for allowed type

🎯 Q1: What are generics in C#?

Generics allow a method or class to work with different types while keeping type safety.

🎯 Q2: Why is List<T> better than List<object>?

List<T> allows only one type and avoids casting errors.

🎯 Q3: What is a generic method?

A generic method uses a type placeholder like <T> and works with different types.

🎯 Q4: What is a generic class?

A generic class uses a type placeholder at class level, like Repository<T>.

🎯 Q5: What is a generic constraint?

A constraint limits what type can be used for T, like where T : IEntity.


🤖Use AI to Learn Faster
⚠️ Important for beginners: Do NOT use AI to write your code yet. Type every example yourself. Your brain learns by doing, not by reading AI output. Use AI only to explain and quiz you — not to code for you. Once you have strong fundamentals, AI becomes a powerful productivity tool for repetitive tasks.

Use ChatGPT, Claude, or Copilot to go deeper on C# generics. Try these prompts:

  • "Explain generics using List<Student>"
  • "Give me 5 practice tasks for generics"
  • "Explain Repository<T> simply"
  • "Quiz me with 5 beginner questions about generics"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

Next Article

Delegates and Events ->

nexcoding.in