23. Generics in C#
Level: Guided
- 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
Trepresenting 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 onlyDictionary<TKey,TValue>- Dictionary with key-value types specified- Generic method - Method with
<T>likePrintList<T> - Generic class - Class with
<T>likeRepository<T> - Constraint - Rule like
where T : IEntity - Type argument - Actual type like
StudentinRepository<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.
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:
- Create
Repository<Teacher> - Add two teachers
- Print all teachers
- Create generic method
FindFirst<T>that returns first item - Test with different types (Student, Teacher, Subject)
See how one generic repository works for all entity types.
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
- Use generics for reusable type-safe code.
- Use
Tfor simple generic type names. - Use clear names like
TEntityfor larger code. - Use constraints only when needed.
- Prefer
List<T>andDictionary<TKey,TValue>over object collections.
Practice Task
Create Repository<T> and use it for:
StudentTeacher
Add two objects to each repository and print them.
Quick Revision
| Question | Answer |
|---|---|
| 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 |
Generics allow a method or class to work with different types while keeping type safety.
List<T> allows only one type and avoids casting errors.
A generic method uses a type placeholder like <T> and works with different types.
A generic class uses a type placeholder at class level, like Repository<T>.
A constraint limits what type can be used for T, like where T : IEntity.
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.