I have received several e-mails asking me about the real use of Generics. Why I like them so much and what makes them such an interesting feature in .NET 2.0. Programmers who use one of many other languages may not have had contact with anything similar to Generics, so I guess that’s quite a legitimate question. Generics are one of the features of the next version of the CLR (Common language runtime), as delivered by Microsoft with .NET 2.0. They can currently be used in the beta and CTP releases of Visual Studio .NET 2005, as well as (in part) in the Mono Project. Now, to explain the use of Generics I thought I’d just use a small and simple sample. If there’s enough interest, I may write other articles on more advanced topics surrounding Generics.
In a project of mine, I used to have some methods that were able to restrict values to a specific range, given as a bottom and a top value. The methods I had looked like this:
public int RestrictValueTop(int value, int top) {
return value < top ? value : top;
}
public int RestrictValueBottom(int value, int bottom) {
return value > bottom ? value : bottom;
}
public int RestrictValue(int value, int bottom, int top) {
return RestrictValueBottom(RestrictValueTop(value, top), bottom);
}
Okay, these three methods complement each other very nicely, so there’s no problem with this. The problem was that I needed similar methods for several other data types, like double
, decimal
, DateTime
and even other integer types like Int64
. The solution was to copy and paste the methods and change the data types. Now, every time I would need support for yet another data type in the same way, I’d have to create a new set of these three methods. This is the kind of problem that Generics offer a solution to: I’m able to write a method that can work with more than just one specific data type.
But wait! Haven’t we been able to do the same thing for a long time? Couldn’t the method look like this:
public IComparable RestrictValueBottom(IComparable value,
IComparable bottom) {
return value.CompareTo(bottom) > 0 ? value : bottom;
}
Right, it could be done that way. But there are several problems with the types here, because we can’t be sure that the two types passed in as value
and bottom
are the same (as they need to be for the CompareTo
method) and we also can’t be sure (as callers of the method) that the type we get returned is the one we expect it to be. The difference in the Generics approach is this: while the legacy “typed” method always works with a specific type and the interface method works with a type that’s never really known for sure, Generics have you specify the type you use at the point in code where you use the method. In the Generics form, that same method would look like this:
public T RestrictValueBottom<T>(T value, T bottom) {
return Comparer<T>.Default.Compare(
value, bottom) > 0 ? value : bottom;
}
The specific type are replaced by a placeholder, T
in this case. Although T
is often used throughout documentation and samples, there’s no need to call the placeholder that. In fact, as soon as more than one placeholder is in place, one should obviously think about giving more meaningful names to them. Now, if you please disregard the exact syntax of the comparison operation itself (the reason why it’s done this way is very well explained here), the method is much same as it used to be. The real difference is that the method is completely typed, as the compiler knows one thing about the types that must be passed in to the method and that are returned: they are the same types, as they are being represented by the same placeholder. A call to this method might look like this:
int foo = RestrictValueBottom<int>(5, 10);
By “passing in” the correct type information between the angle brackets, you define the needed type at the time of the method call. The compiler makes sure you adhere to that definition once you made it, but still your method can be implemented in a type-independent way. That’s the magic of Generics!
This is it for now. Please feel free to comment on this or get back to me by e-mail if you have questions about Generics, maybe there’ll be more to come!