I did some basic search on internet and stackoverflow and I saw quite a lot discussion around overload resolution when both generic version method and non-generic version method are involved. I understand that the overload reslolution is done in compile time - therefore if I have this code:
public class A<T>
{
public void DoStuff(T value)
{
InternalDoStuff(value);
}
protected void InternalDoStuff(int value)
{
Console.WriteLine("Non-generic version");
}
protected void InternalDoStuff(T value)
{
Console.WriteLine("Generic version");
}
}
public class Test
{
static void Main (string [] args)
{
A<int> a = new A<int> ();
a.DoStuff(100);
}
}
The output will be "Generic version" because the resolution of "InternalDoStuff" has been sorted out by compiler and what compiler sees is "InternalDoStuff is called with a T type parameter in DoStuff".
However I dont know if this will make any difference:
public class B : A <int>
{
}
public class Test
{
static void Main (string [] args)
{
B b = new B ();
b.DoStuff(100);
}
}
Now can I say that compiler has enough information to decide "B is a specific version of A", therefore invoke the non-generic version of InternalDoStuff?
Is there any general principle to analyze these kind of overload resolution?
Second approach is not different in any sense to first approach.
Deriving class B from A in no way will change the IL code generated for class A. B is simply inheriting those methods.
If you look at the IL code for class A, you can see that it compiled to call generic version instead of non-generic version -
.method public hidebysig instance void DoStuff(!T 'value') cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: call instance void
ConsoleApplication1.A`1<!T>::InternalDoStuff(!0) <-- Generic version
L_0008: nop
L_0009: ret
}
From Jon Skeet's article here -
Just as a reminder, overloading is what happens when you have two methods with the same name but different signatures. At compile time, the compiler works out which one it's going to call, based on the compile time types of the arguments and the target of the method call. (I'm assuming you're not using dynamic here, which complicates things somewhat.)
As he mentioned using dynamic defer resolution till runtime. This piece of code will call non-generic version method for both of your approaches -
public void DoStuff(T value)
{
dynamic dynamicValue = value;
InternalDoStuff(dynamicValue);
}
Refer to the answers here by Jon Skeet and Eric Lippert describing in detail.