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

前端 未结 4 1503
灰色年华
灰色年华 2021-01-17 11:46

Is any difference between :

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

And

public void Method2(clas         


        
相关标签:
4条回答
  • 2021-01-17 12:24

    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.

    0 讨论(0)
  • 2021-01-17 12:25

    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.

    0 讨论(0)
  • 2021-01-17 12:32

    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.

    0 讨论(0)
  • 2021-01-17 12:47

    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.

    0 讨论(0)
提交回复
热议问题