-1

The method executed is not the one I expected even though the type constraint gives the compiler enough information to choose the correct overloaded method signature

Without the generic method it is calling void DoSomething(IInterface obj) as I expect. With the generic method, void DoSomething<T>(T obj) is instead being called as it is for some reason considered the better candidate in this case.


interface IInterface
{
    void Method();  
}

class A : IInterface
{
    public void Method()
    {

    }
}

public class Program
{
    static void Gen<T>(T obj) where T : IInterface
    {
        DoSomething(obj);
    }

    static void DoSomething<T>(T obj)
    {
        Console.WriteLine("IN GENERIC DO SOMETHING");   
    }

    static void DoSomething(IInterface obj)
    {
        Console.WriteLine("IN INTERFACE DOSOMETHING");
    }

    static void DoSomething(object obj)
    {
        Console.WriteLine("IN OBJ DO SOMRTHING");
    }
    public static void Main()
    {
        IInterface i = new A();
        Gen(i);
    }
}

I expect the non-generic DoSomething method to be called in all cases as the compiler has a concrete type to work with due to the constraint. Instead, the generic DoSomething is being called. It is only when I remove the generic version that the non-generic method is chosen.

Darketh
  • 33
  • 3
  • As the code is, you are calling the unique overload of `Gen`. – Olivier Jacot-Descombes May 18 '19 at 17:24
  • Unfortunately this question looks like a typo. I really don't mean that to reflect negatively on the person asking it. But in a sense it's asking why does calling `Gen` call `Gen`. If calling `Gen` *didn't* call `Gen`, that would be unexpected. – Scott Hannen May 18 '19 at 17:30

1 Answers1

2

It actually makes sense that the generic method is called as it is the most specific of all three.

The interface and the object one are less specific as they both require an upcast while the generic does not.

Moreover : the idea of a generic method is that its behavior is independent of the actual type it is specialized with. In particular, there will be only one specialization generated by the runtime that covers all the reference type cases.

Samuel Vidal
  • 883
  • 5
  • 16
  • 1
    Okay, I was wrong, as he typed the variable as `IInterface`, not as `A`. The solution is simple: **there is only one `Gen` method!** (and a lot of `DoSomething`s) – Olivier Jacot-Descombes May 18 '19 at 16:10
  • Isn't the most specific of the 3 the one ```DoSomething``` that's already overloaded with a specific IInterface concrete type? The constraint already bounds T to be this interface so for all intents and purposes, shouldn't its type be this interface thus not requiring a cast? – Darketh May 18 '19 at 20:08
  • You see, the code of the Gen method is independent of the type T, in that case the generic method is the most specific. I see where you coming from that in the special case where T **is** the interface type then it should be the case that the actual overload with the interface type is more specific. but there is no such special case. A generic method will not be specialized further in the case of a reference type. – Samuel Vidal May 18 '19 at 21:50