我的 C# 源代码中有以下场景:
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);
}
}
当我运行这段代码时,输出是:
"D<A>
选择 a = 5"
“通用 D
选择 a = 5”
这个结果让我很吃惊,因为在这两种情况下我都期望“D<A>
chosen with a = 5”。
我想知道在这种情况下一般的重载决议规则是什么,或者任何导致此输出的内容。此外,我想知道是否有一种方法可以在两种情况下都实现第一个输出。
最佳答案
扩展方法是在编译时仅使用从静态类型系统获取的信息进行解释的语法糖。
以你的第一个例子为例,你有这个:
dispatch.D(a);
dispatch
类型为 Dispatch<A>
,存在扩展方法。所以编译器将其翻译成 DispatchExt.D(dispatch, a)
(非通用版本)。
在你的第二个例子中,你有这个:
d.D(a);
d
类型为 Dispatch<T>
.所以这采用通用扩展方法 DispatchExt.D<T>(d, a)
.
由于转换发生在编译时,因此不考虑实际的运行时类型。
这是顺便说一句。在其他情况下确定重载时使用相同的行为:仅考虑静态编译时类型:
A a = new A();
B b = new B();
A ba = b;
Test(a); // "a"
Test(b); // "b"
Test(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 {}
关于c# - C# 中的重载解析、扩展方法和泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33878866/