Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

interface as argument or generic method with where - what is the difference?

Tags:

c#

generics

Is any difference between :

public void Method1<T>(class1 c, T obj) where T:Imyinterface

And

public void Method2(class1 c, Imyinterface obj)

?

What are the benefits of use the first one method?

like image 472
Rayet Avatar asked Oct 09 '15 14:10

Rayet


Video Answer


2 Answers

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.

like image 131
Grax32 Avatar answered Sep 28 '22 03:09

Grax32


Using a generic method gives you various possibilities with slight signature changes:

  1. public void Method1<T>(class1 c, T obj) where T:Imyinterface, new():
    This allows to instantiate new instances of type T.
  2. public T Method1<T>(class1 c, T obj) where T:Imyinterface:
    This allows you to use the method without casting it's return value when needed.
  3. public void Method1<T>(class1 c, ref T obj) where T:Imyinterface:
    This allows you to assing a new value to obj's reference. Same applies to out.

These are impossible with the non generic version.

like image 26
Amit Avatar answered Sep 28 '22 02:09

Amit