C# Generic

Introduction
Hello all, today I back with another C# topic, and today I will share what i learned about C# Generic. I hope with this article you will know more about C# Generic and use it on your project.
What It Is?
Introduced in C# 2.0, generic provide a placeholder mechanism for defining types in classes, interfaces, or methods that can be replaced with specific types as needed, such as int, float, or string. These placeholders, known as type parameters, allow the same code to work with different data types while maintaining type safety.
Why Implement It?
There are several pros and cons to consider before implement a generic in our project. Here are some of them:
Pros
Enhance code reusability.
Reducing runtime errors related to type mismatches.
Reduce the need to boxing and unboxing by enabling operations on value types directly.
Cons
Could potentially increase code size.
It may be challenging for new programmers to understand.
Could potentially impact performance because the Just-In-Time (JIT) compiler generates specific code for each generic type.
How It Works?
To understand how generic work in the system, let's implement it first. To implement a generic, all you need to do is add <T> after the method or class name, as shown in the code below:
namespace Lncodes.Example.Generic;
public sealed class QuizController<TQuestion, TCorrectAnswer>
{
private readonly TQuestion _question;
private readonly TCorrectAnswer _correctAnswer;
public QuizController(TQuestion question, TCorrectAnswer correctAnswer) =>
(_question, _correctAnswer) = (question, correctAnswer);
}
In the code above, I created a generic QuizController class with generic variables named _question and _correctAnswer. By using generic, I can customize the _question and _correctAnswer variable types as needed. After implementing generic, here's what happens in the system:
When a generic type is defined using a specific reference type, the compiler sets up the generic class with a flexible type parameter. For example, if a
QuizController<T>class is defined with theinttype, the compiler prepares the class for this specific type in Microsoft Intermediate Language (MSIL).When a specific generic class is prepared and the program is running, the Just-In-Time (JIT) compiler generates a specialized version of the generic type. For example, if
QuizController<T>is instantiated with theinttype, the JIT compiler creates aQuizController<int>class at runtime.When a generic type is initialized with previously used type parameters, the system reuses the specialized version of the generic type that was already created by the JIT compiler. This reuse reduces the amount of generated code by minimizing the number of specialized classes created by the JIT compiler.
When assigning a type to a generic, the system by default allows any type to be assigned. However, adding a constraint limits which types can be used. To add a constraint, use the
wherekeyword after the class name. For example, inQuizController where TAnswer : List, theTAnswertype must be aListor any class that inherits fromList.
Console Application
In my console application, I use generic for my QuizController class, allowing me to customize the types of question, answer, and choices based on my needs.
Below is a list of the classes I used to create this console application, along with a brief explanation of each class:
| Class | Description |
| QuizController | This class is used to manage quiz-related operations such as adding and deleting items. |
| Program | This class is used to display the quiz operation on the console. |
In the video above, the console application demonstrates three quiz variations, each using different data types for the answers and choices. All of these variations are managed by a single generic class called QuizController.
By using generic, handling different data types within a single class is greatly simplified. Instead of creating multiple versions of a class to accommodate different data types, a single generic class can be used to handle any type. This flexibility ensures that the code remains cleaner, more consistent, and easier to maintain over time, while also reducing the complexity of managing similar classes.
Additional Information
I have discovered some additional information about C# Generic. If you have any additional information about C# Generic that you'd like to share, please feel free to leave a comment.
Naming Guidelines
When implementing generics, following specific naming guidelines can help ensure code readability and consistency. Here are some naming conventions recommended by Microsoft:
Do use a 'T' prefix with descriptive names for generic type parameters, e.g.
QuizController<TQuestion>.Consider using the single character 'T' for generic type parameters when there is only one type parameter, e.g.
QuizController<T>.Consider using names that indicate the constraints of generic type parameters when the generic has constraints, e.g.
QuizController<TChoicesCollection> where TChoicesCollection : ICollection.
Further Discoveries
Here are some further discoveries I have gathered from various sources that may provide a deeper understanding of C# Generic:
Use generic instead of
objectordynamictypes whenever possible.Objectrequires boxing and unboxing processes, anddynamicrequires runtime type resolution processes, both of which can lead to performance issues. Generic avoid these issues by removing the need for boxing, unboxing, and runtime type resolution, leading to better performance.ℹBoxing is the process of converting a value type, such asint,float, orchar, into anobjecttype. Unboxing is the process of converting anobjecttype into a value type.ℹRuntime type resolution is the process of checking the actual type of a variable, determining its specific type at runtime, and performing operations based on this type to ensure type safety.A generic method can be called without explicitly specifying the type parameter. For example, a generic method
CheckAnswer<int>(int answer)can be invoked usingCheckAnswer(1)instead ofCheckAnswer<int>(1). The compiler automatically infers the type parameter based on the provided argument.A reflection can be used to get information about generic type at the runtime.
💡To learn more about C# Reflection, check out my post at C# Reflection - Last Night Codes.





