C# Tutorial — Generics

Unleash the power of <T> for ultimate code reusability and for convenience when working with multiple data types.

Basura Ratnayake
2 min readJan 15, 2024

The use of Generics facilitates the creation of classes and methods that can work with any data type, be it custom or framework specific. This comes in handy when you want to create code that can be reused with multiple types of data.

This is a relatively easier concept to grasp and has the power to elevate your code reusability to the sky.

Scenario

Display all the values in the collections to the user.

The Wrong Way — What No To Do

namespace Theta.GenericNonGenericDemo;

public class NonGenericDemo {
public List<string> employeeNames = new();
public List<int> employeeIDs = new();
public List<double> employeeSalaries = new();

public NonGenericDemo() {
employeeNames.Add("Namal");
employeeIDs.Add(1021);
employeeSalaries.Add(10000.05);
/* Feel free to populate more employeess :) */
}

public void DisplayEmployeeData(List<string> employees) {
foreach (string data in employees) {
/* Some complex business logic goes here */
Console.Write($"{data} ");
}

/* Just prints a new line, to make it look nice :) */
Console.WriteLine(Environment.NewLine);
}

public void DisplayEmployeeData(List<int> employees) {
foreach (int data in employees) {
Console.Write($"{data} ");
}

Console.WriteLine(Environment.NewLine);
}

public void DisplayEmployeeData(List<double> employees) {
foreach (double data in employees) {
Console.Write($"{data} ");
}

Console.WriteLine(Environment.NewLine);
}
}

In this way, there are multiple DisplayEmployeeData methods to display the data of each collection. This method is only responsible for displaying the data and nothing else therefore;

Now think about a scenario where there are many more data types and you want to modify the DisplayEmployeeData to display data in a different style or manner, you will have to modify each method consuming valuable time and resources.

The Right Way — Reusability

namespace Theta.GenericNonGenericDemo;

public class GenericDemo {
public List<string> employeeNames = new();
public List<int> employeeIDs = new();
public List<double> employeeSalaries = new();

public GenericDemo() {
employeeNames.Add("Namal");
employeeIDs.Add(1021);
employeeSalaries.Add(10000.05);
/* Feel free to populate more employeess :) */
}

/* T - can be any name */
public void DisplayEmployeeData<T>(List<T> employees) where T : notnull {
foreach (T data in employees) {
/* Some complex business logic goes here */
Console.Write($"{data} ");
}

/* Just prints a new line, to make it look nice :) */
Console.WriteLine(Environment.NewLine);
}
}

In this way, there’s only method DisplayEmployeeData to handle and display data. This method can handle any data type. The T inside of <T> can be any allowed name.

public void DisplayEmployeeData<T>(List<T> employees) where T : notnull

The keyword where is optional here but with this keyword, we can specify certain restrictions for the what the method receives as input.

Remember

Things to remember about using Generic types.

  • You can maximise code reuse, performance and readability.
  • You can create your own generic methods, interfaces, classes or delegates.
  • Use proper validations to ensure the full power of generic data types.

--

--

Basura Ratnayake

Experienced Full Stack Software Engineer Passionately In ❤️ With Freedom, Sri Lanka, Technology, and History.