C#中的重载解析,扩展方法和通用性 [英] Overload resolution, extension methods and genericity in C#
问题描述
class A {}
class Dispatch< T> {}
static class DispatchExt
{
public static void D< T>(this Dispatch< T> d,int a)
{
Console.WriteLine(Generic D with a =+ a.ToString());
$ b $ public static void D(this dispatch< A> d,int a)
{
Console.WriteLine(D&A; with a = + a.ToString());
class程序
{
static void D< T>(Dispatch< T> d,int a)
{
dD(a);
}
static void Main(string [] args)
{
int a = 5;
var dispatch = new Dispatch< A>();
dispatch.D(a);
D(派送,a);
$ / code>
当我运行这段代码时,输出是:
Generic D
选择a = 5
这个结果令我感到惊讶,因为我期待 code> D< A> 在两种情况下都选择a = 5。
我想知道这种情况下的一般重载解决规则是什么,或者是什么导致这个输出。此外,我想知道是否有办法在两种情况下实现第一个输出。
扩展方法是在编译时使用仅从静态类型系统获取的信息进行解释的语法糖。 >
以你的第一个例子,你有这个:
pre $ dispatch.D(a );
dispatch
类型调度< A>
,为此存在扩展方法。因此,编译器将其转换为 DispatchExt.D(dispatch,a)
(非通用版本)。
在你的第二个例子中,你有这个:
dD(a);
d
类型为调度< T>
。因此,这需要通用扩展方法 DispatchExt.D< T>(d,a)
。
发生在编译时,实际的运行时类型没有考虑到。
这是btw。在其他情况下确定重载时使用的行为相同:仅考虑静态编译时类型:
A a =新的A();
B b = new B();
A ba = b;
测试(a); //a
测试(b); //b
测试(ba); //a
使用以下定义:
public void Test(A a){Console.WriteLine(a); }
public void Test(B a){Console.WriteLine(b); }
public class A {}
public class B:A {}
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 {}
这篇关于C#中的重载解析,扩展方法和通用性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!