I am reading existing posts on Generics at SO. If Generics has so many advantages like Type safety, no overhead of boxing/unboxing and it is fast, why not always use it? Why
In general you should - however, there are times (especially when writing library code) when it is not possible (or certainly not convenient) to know about the calling type (even in terms of T
), so non-generic types (mainly interfaces such as IList
, IEnumerable
) are very useful. Data-binding is a good example of this. Indeed, anything that involves reflection is generally made much harder by using generics, and since (via the nature of reflection) you've already lost those benefits, you may as well just drop to non-generic code. Reflection and generics are not very good friends at all.
Generics makes the code much more reusable, add type safety etc. If you see any good API (Jdk, Scala etc) you will see Generics everywhere. The biggest challenge with Generics is, it's bit tricky to get used to with it and hence many programmer find generics not readable code.
But then here we should fix the real problem (bridging knowledge Gap ) instead of avoiding Generics.
Generics may be fast and type safe, but also add complexity (another dimension which can vary and must be understood by programmers). Who is going to maintain your code? Not every trick with generics (or lambdas, or dependency injection, or...) is worth it. Think about what problem you are going to solve, and what parts of that problem may change in the future. Design for those cases. The optimally flexible software is too complex to be maintained by mortal programmers.
Sometimes "object" collections are simply unavoidable. Often this happens when there's multiple types in the same control/collection - the only type they have in common is "object", and so that's the best type for your collection.
Another case for object (non collection related) that pops up from time to time can be seen with the PropertyGrid. A third party property grid may allow you to attach a "validator" which returns whether the users new value for a given property on the grid is acceptable. As the PropertyGrid does not know what properties it will be displaying, the best it can give the validator is an object - even though the validator knows exactly what type it will be called with.
But as per Mark's answer - most (all?) of the non generic collections in .NET are only there for legacy reasons. If .NET was remade today you can be sure the standard library would look very different.
Generics is the way to go generally. Added complexity could be one argument against it, but imo it's totally worth considering the benefits in most cases. As a general rule of thumb, embrace it. Reflection is another case which generics makes it harder. But I avoid generics only if it doesn't make sense.
The one scenario where I like to avoid generics is making a method generic when it serves no intended purpose of generics and can be misleading. Generics was introduced for better type safety and performance (when it comes to value types). If it serves neither, then a generic approach can be misleading to developer. For example consider the snippet from this question:
public void DoSomething<T>(T request)
{
if (request == null)
throw new ArgumentNullException("request");
if (request is ISomeInterface)
DoSomething();
else
DoSomethingElse();
}
There is nothing generically handled in the above method. Its even worse when you do a lot of type checking in a generic method:
public void DoSomething<T>(T request)
{
if (typeof(T) == typeof(X))
DoSomething();
else if (typeof(T) == typeof(Y))
DoSomethingElse();
...
}
which completely defeats the logic of generics. There are better patterns to avoid type checking, but if it is absolutely necessary, then accepting object
as parameter is what I would prefer. Another similar case is when value types are anyway boxed in a generic method:
public void DoSomething<T>(T request)
{
var type = request.GetType(); //boxed already in case of value types.
//or other reflection calls which involves boxing
}
By seeing the method definition one is tempted to think of this method not having boxing penalties, but letting the caller know it clearly is one good way. I like it like:
public void DoSomething(object request) //boxes here
{
var type = request.GetType();
//or other reflection calls which involves boxing
}
Other than that, I prefer generics all the time.
An edge case where the two could behave differently is with dynamic
.
public void Generic<T>(T request)
{
}
public void Object(object request)
{
}
dynamic d = null;
Object(d); //no issues
Generic(d); //run-time explosion; can not infer type argument
Not a factor to consider, just a silly difference in behaviour worth having in mind.