I have the following scenario in my C# source:
class A{}
class Dispatch<T>{}
static class DispatchExt
{
public static void D<T>(this Dispatch<T> d, int a)
{
Console.WriteLine("Generic D chosen with a = " + a.ToString());
}
public static void D(this Dispatch<A> d, int a)
{
Console.WriteLine("D<A> chosen with a = " + a.ToString());
}
}
class Program
{
static void D<T>(Dispatch<T> d, int a)
{
d.D(a);
}
static void Main(string[] args)
{
int a = 5;
var dispatch = new Dispatch<A>();
dispatch.D(a);
D(dispatch, a);
}
}
When I run this code the output is:
"D<A>
chosen with a = 5"
"Generic D
chosen with a = 5"
That result surprised me, because I was expecting "D<A>
chosen with a = 5" in both situations.
I would like to know what are the general overload resolution rules in this scenario, or anything that cause this output. Furthermore, I wonder if there is a way to achieve the first output in both situations.
Extension methods are syntactic sugar that is interpreted at compile-time using information taken from the static type system only.
Taking your first example, you have this:
dispatch.D(a);
dispatch
is of type Dispatch<A>
, for which an extension method exists. So the compiler translates this into DispatchExt.D(dispatch, a)
(the non-generic version).
In your second example, you have this:
d.D(a);
d
is of type Dispatch<T>
. So this takes the generic extension method DispatchExt.D<T>(d, a)
.
Since the translation happens at compile-time, the actual run-time type is not taken into account.
This is btw. the same behavior used when determining overloads in other situations: Only the static compile-time type is taken into account:
A a = new A();
B b = new B();
A ba = b;
Test(a); // "a"
Test(b); // "b"
Test(ba); // "a"
Using the following definitions:
public void Test(A a) { Console.WriteLine("a"); }
public void Test(B a) { Console.WriteLine("b"); }
public class A {}
public class B : A {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With