What is the difference between this:
void MyMethod(IMyInterface value)
{
//...
}
and this:
void MyMethod<T>(T value) where T : IMyInterface
{
//...
}
What is the difference between this:
void MyMethod(IMyInterface value)
{
//...
}
and this:
void MyMethod<T>(T value) where T : IMyInterface
{
//...
}
The generic version will require .NET 2.0.
But seriously, while they look similar, there are fundamental differences between them. One difference is, at runtime, the JIT compiler will generate code for each value type that will be used for the generic version. The non-generic version will require the value types to be boxed in order to be passed to the function.
The difference will also matter when dealing with delegates. The signature of MyMethod<int>
matches void MyDelegate(int x)
while the non-generic version is not matched.
The main functional difference is that you can know the actual type of the object inside of the generic method. The T parameter will contain the actual type which can advantageous in certain scenarios.
In the non-generic case you cannot guarantee access to the underlying type of the object. Most of the type you could grab value.GetType() but the user could pass Null and thwart you.
Jared has mentioned some of the points; another interesting one: with generics, you can avoid boxing of value-types as long as you basically don't touch it... so I could have a struct Foo : IMyInterface
and pass it in, and it won't get boxed.
The difference gets more noticeable with things like collections:
static void Foo(IEnumerable<IMyInterface> data) {}
vs
static void Foo<T>(IEnumerable<T> data)
where T : IMyInterface {}
Now, since C# 3.0 doesn't have covariance (except for arrays), I can't pass a List<Bar>
to the top one, even if Bar : IMyInterface
- but I can with the second (implicit T = Bar
).
Another caveat to consider with this scenario is the fact that using "where T : <%your base interface or abstraction%>" can be overused in generics rendering your generic type non-generic in nature.
IE: Remember that by isolating your generic method to IMyInterface, you're isolating that method to only those types implementing IMyInterface. So if you've merely chosen to use IMyInterface based on good OOP principles, but you have only one (or in some cases a very small number of) potential type anywhere that'll be implementing that interface, then you've defeated the purpose of using generics. Under that circumstance, the first option would be better.
Only use "where" on your generic type when you're going to have a broader range of types that actually implement IMyInterface.
Another difference, using the generic method allows you to specify multiple interfaces that your object must implement:
class Dictionary<TKey,TVal>
where TKey: IComparable, IEnumerable
where TVal: IValue
{ ... }