Xin*_*hao 5 c# generics overload-resolution
我在Internet和stackoverflow上进行了一些基本搜索,当涉及通用版本方法和非通用版本方法时,我看到了很多有关重载解析的讨论。我知道重载再分解是在编译时完成的-因此,如果我有以下代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出将是“通用版本”,因为编译器已经选择了“ InternalDoStuff”的分辨率,并且编译器看到的是“在DoStuff中使用T类型参数调用了InternalDoStuff”。
但是我不知道这是否会有所作为:
public class B : A <int>
{
}
public class Test
{
static void Main (string [] args)
{
B b = new B ();
b.DoStuff(100);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以说编译器具有足够的信息来确定“ B是A的特定版本”,因此可以调用InternalDoStuff的非泛型版本吗?
是否有任何一般原则来分析此类过载解决方案?
第二种方法在任何意义上与第一种方法没有什么不同。
从 A 派生类 B 绝不会改变为类 A 生成的 IL 代码。B 只是继承这些方法。
如果您查看 A 类的 IL 代码,您可以看到它被编译为调用通用版本而不是非通用版本 -
.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
}
Run Code Online (Sandbox Code Playgroud)
来自Jon Skeet 的文章-
提醒一下,当两个方法具有相同名称但签名不同时,就会发生重载。在编译时,编译器根据参数的编译时类型和方法调用的目标确定要调用哪一个。(我假设您在这里没有使用动态,这使事情变得有些复杂。)
正如他提到的,使用动态延迟解析直到运行时。这段代码将为您的两种方法调用非通用版本方法 -
public void DoStuff(T value)
{
dynamic dynamicValue = value;
InternalDoStuff(dynamicValue);
}
Run Code Online (Sandbox Code Playgroud)
请参阅Jon Skeet和Eric Lippert的答案,详细描述。