Generics are related to the idea of Templates in C++.
They permit classes, structs, interfaces, delegates, and methods to be parameterized by the types of data they store
and manipulate. Without generics, general purpose methods or
data structures (like Lists, Stacks, etc.) typically use the built-in Object type to store data of any type.
While the use of the built-in Object type makes the implementation very flexible,
it has drawbacks with regards to Performance and Type Safety.
For example, it is possible to use any user defined type, e.g. TeacherClass, as a parameter in calls to these general purpose classes. However, the general purpose data structures cannot be sure that the type passed in is what is expected. If it is not, it frequently results in ugly runtime errors in the application. Also, if the type is returned from the method call after processing,
the result must explicitly be cast back to the appropriate type, which adds further overhead. Generics provide a way to create strongly typed parameters, allowing reuse of the general purpose routine without the associated type safety issues and the overhead of run-time type checking. Generics are available to any .NET language in the .NET Framework 2.0.