Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the overloaded method getting called?

Tags:

c#

.net

I thought the method that is getting called is decided runtime, or have I missed something? Sample code:

class Program
{
    static void Main(string[] args)
    {
        var magic = new MagicClass();
        magic.DoStuff(new ImplA());
        magic.DoStuff(new ImplB());
        Console.ReadLine();
    }
}
class MagicClass
{
    internal void DoStuff<T>(T input) where T : SomeBase
    {
        HiThere(input);
    }

    void HiThere(SomeBase input)
    {
        Console.WriteLine("Base impl");
    }

    void HiThere(ImplA input)
    {
        Console.WriteLine("ImplA");
    }

    void HiThere(ImplB input)
    {
        Console.WriteLine("ImplB");
    }
}

abstract class SomeBase
{

}
class ImplA : SomeBase{}
class ImplB : SomeBase{}

I thought I would get:

ImplA
ImplB

as output but it prints Base impl. Is there anything I can do to get the overloaded method without casting the input?

like image 305
Tomas Jansson Avatar asked Apr 12 '13 07:04

Tomas Jansson


2 Answers

Overloads are chosen by the compiler. For the call here:

internal void DoStuff<T>(T input) where T : SomeBase
{
    HiThere(input);
}

it chooses the one with SomeBase, because that's all it has at compile time.

What you most probably want is overrides. This means that the different logic has to be put into the inheritors of SomeBase:

abstract class SomeBase
{
  abstract string Name { get; }
}
class ImplA : SomeBase{ override string Name { get { return "ImplA"; } } }
class ImplB : SomeBase{ override string Name { get { return "ImplB"; } } }

void HiThere(SomeBase input)
{
    Console.WriteLine(input.Name);
}
like image 195
Stefan Steinegger Avatar answered Nov 14 '22 20:11

Stefan Steinegger


Overloads are selected during compilation.
Overrides are selected during runtime.

Here, compilers only knows that T can be assigned to SomeBase, but nothing else. Actually, if it worked as you expected, you would be able to completely skip the where T : SomeBase part. The reason you need it is that compiler needs to know that information in order to check what can be called on the provided object.

like image 45
Zdeslav Vojkovic Avatar answered Nov 14 '22 19:11

Zdeslav Vojkovic