Generics
- Renee Li
- Oct 17
- 4 min read
In another blog, we talked about .NET Framework, which includes Generics.
So, today, let's extend on Generics - generic containers List<T>.
Okay, I have a confession to make before I even start. I have already done a small projects that involved generic <T>, delegate, and lambda function. It took me a week to study cover these three concepts, and also regarding serialization. I also have a finished small program that I will show later on. But even with all the groundworks I have done, I still struggled in applying Generics concepts.
After team up with Copilot, I begin to have a clearer concepts about Generics.
Before I give my thought, let me quickly introduce the little program I did to help me understand Generics.
Account attributes
account names
balance ( to simplified the program, I hardcode balance = 100.)
User Interface
1= Student
2 = Staff
3 = Exit
Goal is to
put student objects into a list named, student list;
put staff objects into a list named, staff list.
So, I was confused about creating a generic class to create and add list or generics has built in functions. In stead of just show the conclusion, I provide the whole learning journey here that helps me figure out.
Also, for the purpose of Vibe Coding, I will also document my conversation with Copilot here:
i see! so if just to put labels on data to separate them, there is no need to even create child class, we can simply treat them as one class and put different label. but for some list, we want extra data then other classes, we then need create child class and treat them differently.
Your Insight:
“If I just want to label data, I don’t need child classes. But if I want different data or behavior, I do.”
✅ Exactly.
Same behavior, same structure → use one class (Account) and separate lists.
Different behavior or extra fields → subclass (StudentAccount, StaffAccount) and treat them differently.
🧩 Metaphor: The Backpack System 🎒
Imagine every person carries a backpack:
If all backpacks are the same, just label them: “Student”, “Staff”
If students carry textbooks and staff carry laptops, you need different backpack designs — subclass!
so can you re-write the main and all helper class for me please. to make it simple, let's just hard code balance with 100.00 for any accounts. don't worry about account numbers for now. so for Account class, attributes just account name and balance. i want user to choose between 1,2 or 3. 1 = student, 2 = staff, and 3 = exit the program. for 1 = student, we create an Account object for each student , studentname = _studentname, balanace = 100. then we put these student objects into a list called StudentList. For 2 = staff, we create an account object for each staff, staffname = staffinname, balance = 100, then we put these staff objects into a list called StaffList. Can you please give me the code
using System;
using System.Collections.Generic;
namespace GenericCopilot
{
public enum UserType
{
Student = 1,
Staff = 2,
Exit = 3
}
public static class ListHelper
{
public static void AddItem<T>(List<T> list, T item)
{
list.Add(item);
}
}
public class Program
{
private static List<Account> StudentList = new List<Account>();
private static List<Account> StaffList = new List<Account>();
private static void Main(string[] args)
{
UserType option;
do
{
option = GetUserType();
switch (option)
{
case UserType.Student:
CreateStudentAccount();
break;
case UserType.Staff:
CreateStaffAccount();
break;
}
} while (option != UserType.Exit);
Console.WriteLine("\nExiting the program. Goodbye!");
}
private static UserType GetUserType()
{
while (true)
{
Console.WriteLine("\nChoose an option:");
Console.WriteLine("1 = Create Student Account");
Console.WriteLine("2 = Create Staff Account");
Console.WriteLine("3 = Exit");
Console.Write("Your choice: ");
string input = Console.ReadLine();
if (int.TryParse(input, out int choice) &&
Enum.IsDefined(typeof(UserType), choice))
{
return (UserType)choice;
}
Console.WriteLine("Invalid input. Please enter 1, 2, or 3.");
}
}
private static void CreateStudentAccount()
{
Console.Write("Enter student name: ");
string name = Console.ReadLine();
if (string.IsNullOrWhiteSpace(name))
{
Console.WriteLine("Invalid name. Try again.");
return;
}
Account student = new Account(name);
ListHelper.AddItem(StudentList, student);
Console.WriteLine("Student account created:");
Console.WriteLine(student);
}
private static void CreateStaffAccount()
{
Console.Write("Enter staff name: ");
string name = Console.ReadLine();
if (string.IsNullOrWhiteSpace(name))
{
Console.WriteLine("Invalid name. Try again.");
return;
}
Account staff = new Account(name);
ListHelper.AddItem(StaffList, staff);
Console.WriteLine("Staff account created:");
Console.WriteLine(staff);
}
}
}namespace GenericCopilot
{
public class Account
{
public string Name { get; set; }
public double Balance { get; set; }
public Account(string name)
{
Name = name;
Balance = 100.00;
}
public override string ToString()
{
return $"Account Name: {Name}, Balance: {Balance:C}";
}
}
}
So, above was what Copilot provided to me.
List<Account> xxx = new List<Account> is an implementation of Generics List<T>. There is no need to create a separate class to create list and add method.
private static List<Account> StudentList = new List<Account>();
private static List<Account> StaffList = new List<Account>();List Helper static class is the implementation of add method.
public static class ListHelper
{
public static void AddItem<T>(List<T> list, T item)
{
list.Add(item);
}
}There are still a lot more about Generics, which I will explore in following blogs.

Comments