Before generics the only strongly-typed collection available were arrays. Collection classes such as ArrayList and Stack deal with the object
type.
Besides the risk of InvalidCastException
when trying to use objects coming back from these collections, performance also suffers for value-types stored in collections as they need to be wrapped in a new object (boxed), and subsequently unboxed again when retrieved.
Generics allow a type (or method) to accept other types as parameters using <>
syntax. They can then refer to those type parameters throughout their implementation wherever a type would normally be specified, e.g. for return variables, properties, parameters etc.
This allows a class to be further specialized for working with other classes. .NET uses Generics extensively for its collection classes and it is a core requirement for LINQ query expressions C# 3.0.
Code
Queue<Job> work = new Queue<Job>();
work.Push(new Job("Launch the product"));
// Don't worry only a Job can be in the work queue
Job next = work.Pop();
Queue work = new Queue();
work.Push(new Job("Launch the product"));
// Hope nobody pushes an object that isn't a Job
Job next = (Job)work.Pop();
Notes
- Unlike similar functionality in C++ (Templates) or Java (Generics) the C# runtime generates these generic methods and classes at runtime preserving type metadata that can be examined via Reflection
- The feature was developed by Microsoft Research
- Before generics some developers wrote tailored collection classes (or wrappers) for the specific type they want the collection class to managed. e.g.
StringList
while others created tailored collection classes using tools like CodeSmith