考虑这个代码片段,其中包含泛型和重载函数:
我认为它不会编译,因为我有两个适合OverloadedFunction的候选方法,但它确实编译并打印出“U”。
在生成的IL中,我可以看到:
意味着C#编译器将对OverloadedFunction的调用解析为一次调用,而不是所需的“通用”函数调用调用virt。我可以猜测从编译器的角度来看,“U”方法是更好的选择,但我无法确切地解释为什么...
我真的很想理解这里发生了什么,但我一点头绪也没有。
但如果考虑这个修改后的片段,引入另一个间接层级,情况变得更加奇怪:
我希望这个程序仍然打印出 'U',因为 'V' 是通过继承与 'U' 相关的。但是它打印出 'T',如 MSIL 所示:
using System;
namespace Test_Project
{
public interface Interface
{
void f();
}
public class U : Interface
{
public void f() {}
}
public class Class<T> where T: Interface
{
public static void OverloadedFunction(T a)
{
Console.WriteLine("T");
a.f();
}
public static void OverloadedFunction(U a)
{
Console.WriteLine("U");
a.f();
}
}
class Program
{
public static void Invoke(U instance)
{
Class<U>.OverloadedFunction(instance);
}
static void Main(string[] args)
{
Invoke(new U());
}
}
}
我认为它不会编译,因为我有两个适合OverloadedFunction的候选方法,但它确实编译并打印出“U”。
在生成的IL中,我可以看到:
.method public hidebysig static
void Invoke (
class Test_Project.U 'instance'
) cil managed
{
// Method begins at RVA 0x2085
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call void class Test_Project.Class`1<class Test_Project.U>::OverloadedFunction(class Test_Project.U)
IL_0006: ret
} // end of method Program::Invoke
意味着C#编译器将对OverloadedFunction的调用解析为一次调用,而不是所需的“通用”函数调用调用virt。我可以猜测从编译器的角度来看,“U”方法是更好的选择,但我无法确切地解释为什么...
我真的很想理解这里发生了什么,但我一点头绪也没有。
但如果考虑这个修改后的片段,引入另一个间接层级,情况变得更加奇怪:
using System;
namespace Test_Project
{
public interface Interface
{
void f();
}
public class U : Interface
{
public void f() {}
}
public class V : U { }
public class Class<T> where T: Interface
{
public static void OverloadedFunction(T a)
{
Console.WriteLine("T");
a.f();
}
public static void OverloadedFunction(U a)
{
Console.WriteLine("U");
a.f();
}
}
class Program
{
public static void Invoke(V instance)
{
Class<V>.OverloadedFunction(instance);
}
static void Main(string[] args)
{
Invoke(new V());
}
}
}
我希望这个程序仍然打印出 'U',因为 'V' 是通过继承与 'U' 相关的。但是它打印出 'T',如 MSIL 所示:
.method public hidebysig static
void Invoke (
class Test_Project.V 'instance'
) cil managed
{
// Method begins at RVA 0x208d
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call void class Test_Project.Class`1<class Test_Project.V>::OverloadedFunction(!0)
IL_0006: ret
} // end of method Program::Invoke
这意味着C#编译器更喜欢使用通用版本。
请问有人能解释一下在涉及泛型参数和继承时,方法重载的解析规则是什么吗?