Reputation: 23472
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?
Upvotes: 13
Views: 348
Reputation: 14591
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.
Upvotes: 4
Reputation: 64628
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);
}
Upvotes: 18