Is any difference between :
public void Method1(class1 c, T obj) where T:Imyinterface
And
public void Method2(clas
Using a generic method gives you various possibilities with slight signature changes:
public void Method1<T>(class1 c, T obj) where T:Imyinterface, new()
:public T Method1<T>(class1 c, T obj) where T:Imyinterface
:public void Method1<T>(class1 c, ref T obj) where T:Imyinterface
:obj
's reference. Same applies to out
.These are impossible with the non generic version.
As noted, with void methods, there is not much difference in usage.
If you look behind the scenes you will see that with the generic method, .NET will compile a separate method for each type you call it with. This has the effect of avoiding boxing when called with a struct.
The big difference occurs when you use a return type.
public T Method1<T>(class1 c, T obj) where T: IMyInterface
and
public IMyinterface Method2(class1 c, IMyInterface obj)
With the generic version, you get the original type back, so you can continue calling properties or methods (instance or extension) on the original type.
With the non-generic version, you only get back a value of type IMyInterface
, so you can only call properties or methods that are part of IMyInterface
.
This is most interesting, in my book, when used with extension methods and a fluent-style API.
public static T Move<T>(this T animal) where T : ICanMove
{
return animal;
}
public static T Fly<T>(this T animal) where T : ICanFly
{
return animal;
}
public static T Pounce<T>(this T animal) where T : ICanPounce
{
return animal;
}
Given that Tiger implements ICanMove and ICanPounce and the Eagle implements ICanMove and ICanFly, I can call the above extension methods that apply to the original type. Intellisense will show .Fly() and .Move() available for an Eagle, and .Pounce() and a .Move() for a Tiger.
var birdie = new Eagle();
birdie
.Move()
.Fly()
.Move()
.Fly();
var kitty = new Tiger();
kitty
.Move()
.Pounce()
.Move()
.Pounce();
Here is what it would look like if you implemented Move non-generically:
public static ICanMove Move<T>(this ICanMove animal)
{
return animal;
}
Since an ICanMove interface is returned, the compiler has no idea that it was originally an Eagle or a Tiger, and so you can only use extensions, methods, or properties that are part of the ICanMove interface.
While in your scenario it's practically the same (except for the fact that with method accepting interface parameter it will upcast concrete object to interface type) consider slightly different scenario. Let's say we want our method to accept only class that implements two interfaces IMyInterface1
and IMyInterface2
and that otherwise code should not compile :
interface IMyInterface1 { }
interface IMyInterface2 { }
class MyClass : IMyInterface1 { }
public void Method1<T>(Class1 c, T obj) where T : IMyInterface1, IMyInterface2
{
}
If we create method that accepts interface as it's second parameter it will not satisfy the condition because it doesn't restrict user from sending class instance that implements only one interface but doesn't implements the second interface like it is for MyClass and IMyInterface2 in this example.
And what interface should user send ? He don't really know the type that needs to send on compile-time.
This is a good spot to use generic and generic constrains and on the other hand we cannot use single interface parameter.
There is no big difference for void
methods.
public void Method1<T>(class1 c, T obj) where T : Imyinterface
equals to
public void Method2(class1 c, Imyinterface obj, Type t)
where t
must be Imyinterface
.
So if you need to pass some Type
to your method, and you need to apply some constraints to that Type
at compile-time, use the generic method.