为什么要通过"动态过载"进行双重调度?基于参数类型是不是由C#原生支持?我发现这需要动态调度,但由于虚拟方法调用也是动态调度的,因此对语言来说并不奇怪。那么为什么这个功能不属于C#呢?使用Reflection实现此功能的最优雅的解决方案是什么(可能有一些库)?
class Program
{
static void Main(string[] args)
{
var objs = new object[] { new Class1(), new Class2() };
foreach (var item in objs)
{
Method(item);
}
}
static void Method(Class1 obj)
{
}
static void Method(Class2 obj)
{
}
}
class Class1
{
}
class Class2
{
}
更新确实,因为此示例中的Method
不是虚拟的并且只接受一个参数,所以这仍然是单个调度但是"基数"发送的问题在这个问题中并不重要,只要它是> 0
答案 0 :(得分:10)
virtual
用于单次发送。如果您需要双重发送,可以在C#中执行此操作:
var objs = new object[] { new Class1(), new Class2() };
foreach (var item in objs)
{
Method((dynamic)item);
}
这将使编译器以非常不同的方式解释对方法的调用。它将发出一个所谓的调用站点,它将在运行时确定应该调用哪个方法。这也称为后期绑定。
在这个具体示例中,您仍然可以获得单个调度,但如果Method
是虚拟的,那么它将是双重调度。
这对于快速实现访问者模式非常方便,但请注意,这将比传统的手动双重调度慢。因此,您可能希望在性能敏感的代码中使用旧的方法。
答案 1 :(得分:4)
为什么要通过"动态过载"进行双重调度?基于参数类型是否由C#本身支持?
static void Main(string[] args)
{
var objs = new object[] { new Class1(), new Class2() };
// Note the change of type for item to "dynamic"
foreach (dynamic item in objs)
{
Method(item);
}
}
涉及编译时类型为dynamic
的值的操作是后期绑定的 - 因此,在执行时根据值的实际类型执行重载解析。除了重载解析之外,动态类型还有很多,当然,包括能够通过代码动态提供成员的类型。
所有这些都有性能影响 - 但有时它是最干净的方法。
您可能希望使用object
类型的参数添加额外的重载作为" catch-all"如果一个值与其他任何重载都没有匹配......虽然如果你的数组包含一个null元素,它仍然是不明确的。
答案 2 :(得分:3)
如果你真的感兴趣的话,.Net CLR仿制药的设计者之一Andrew Kennedy写了一篇关于此的文章。
http://research.microsoft.com/pubs/64039/transposingftocsharp.pdf
由于具有真正参数化多态性的F#使用相同的公共语言运行时,可能C#也可以实现它,并且决定是保留C ++ / C#语言风格。
从他的文章:"同样,多态虚拟方法[10]的CLR实现涉及执行时代码生成,与足以支持非虚拟多态方法的加载时代码生成形成对比。 #34;