C# 是单调度语言还是多调度语言?
Posted
技术标签:
【中文标题】C# 是单调度语言还是多调度语言?【英文标题】:Is C# a single dispatch or multiple dispatch language? 【发布时间】:2010-10-03 13:20:15 【问题描述】:我正试图准确地理解什么是单调度和多调度。
我刚读到这个:http://en.wikipedia.org/wiki/Multiple_dispatch
从这个定义来看,在我看来,C# 和 VB.Net 是多调度的,即使在编译时选择调用哪个重载。
我在这里是正确的,还是我遗漏了什么? 谢谢!
【问题讨论】:
【参考方案1】:好的,我理解函数重载与多分派的细微差别。
基本上,区别在于调用哪个方法是在运行时还是编译时选择的。现在,我知道每个人都这么说,但是没有一个明确的例子,这听起来很明显,因为 C# 是静态类型的,而多调度语言(至少对我来说显然)似乎是动态类型的。到现在为止,就这个定义而言,多重分派和函数重载对我来说听起来完全一样。
真正不同的情况是,当您有 2 个在参数类型上不同的方法重载时,但是这 2 个类型是多态的,并且您使用声明为更高类型的引用进行调用,它具有较低类型的对象... (如果有人能想到更好的表达方式,请随时编辑此答案)
例子:
int CaptureSpaceShip(IRebelAllianceShip ship)
int CaptureSpaceShip(XWing ship)
void Main()
IRebelAllianceShip theShip = new XWing();
CaptureSpaceShip(theShip);
XWing 显然实现了 IRebelAllianceShip。 在这种情况下,将调用第一个方法,而如果 C# 实现了多次调度,则将调用第二个方法。
对文档重新散列感到抱歉...在我看来,这似乎是解释这种差异的最清楚的方式,而不仅仅是阅读每个调度方法的定义。
更正式的解释: http://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_is_more_than_function_overloading
【讨论】:
这是主要区别的一个很好的例子。 谢谢!我需要一个这样的例子。 @Daniel Magliola,请注意动态调度现在可以在 C# 4.0 中使用动态 “多调度语言似乎是动态类型的”。在阅读了perl.com/pub/2007/12/06/soto-11.html?page=1,这就是我提出这个问题的方式之后,我认为它实际上是相反的(参见他说“将类型放入 Perl 6 的主要原因不是强类型,而是多个派遣”)。如果您要根据参数类型决定调用什么方法,您可能需要有一个具有显式类型的方法定义,这是动态类型语言通常没有的(至少我见过的语言) )。 @David Mulfrod 的答案(新的动态关键字)应该是正确的答案——也就是说,如果你愿意,那么你可以让 CLR 进行动态调度(我猜 JVM 的调用动态是类似的,但它不是可用于 Java)【参考方案2】:对于那些使用搜索引擎找到这篇文章的人,C# 4.0 引入了dynamic 关键字。代码如下所示。
int CaptureSpaceShip(IRebelAllianceShip ship)
int CaptureSpaceShip(XWing ship)
void Main()
IRebelAllianceShip theShip = new XWing();
CaptureSpaceShip((dynamic)theShip);
【讨论】:
+1。 C# 4.0 支持多重分派。以下版本不 称为动态调度。多重分派只是能够进行动态参数类型解析的副产品。【参考方案3】:C# 是单一调度,但有些博客文章的标题看起来像是在尝试模拟多方法。如果我可以加载其中一篇文章,我将在此处更新我的答案。
【讨论】:
【参考方案4】:也许有人会对使用动态关键字 (MSDN blog) 进行多次调度的良好 C# 示例 感兴趣
class Animal
class Cat : Animal
class Dog : Animal
class Mouse : Animal
我们可以为同一个方法创建多个重载,根据其参数类型的不同组合进行专门化:
void ReactSpecialization(Animal me, Animal other)
Console.WriteLine("0 is not interested in 1.", me, other);
void ReactSpecialization(Cat me, Dog other)
Console.WriteLine("Cat runs away from dog.");
void ReactSpecialization(Cat me, Mouse other)
Console.WriteLine("Cat chases mouse.");
void ReactSpecialization(Dog me, Cat other)
Console.WriteLine("Dog chases cat.");
现在是神奇的部分:
void React(Animal me, Animal other)
ReactSpecialization(me as dynamic, other as dynamic);
这是因为“动态”强制转换,它告诉 C# 编译器,而不是仅仅调用 ReactSpecialization(Animal, Animal),动态检查每个参数的类型并在运行时选择要调用的方法重载.
为了证明它确实有效:
void Test()
Animal cat = new Cat();
Animal dog = new Dog();
Animal mouse = new Mouse();
React(cat, dog);
React(cat, mouse);
React(dog, cat);
React(dog, mouse);
输出:
Cat runs away from dog.
Cat chases mouse.
Dog chases cat.
Dog is not interested in Mouse.
***说 C# 4.0(动态)是“多调度”语言。 我也认为 Java、C#(4.0 之前)、C++ 等语言是单调度的。
【讨论】:
【参考方案5】:C# 不支持多分派。访问者设计模式模拟了可以被描述为多次分派的东西,尽管访问者模式主要关注的是从层次结构中分离算法。
【讨论】:
【参考方案6】:根据cited Wikipedia article,多重分派,顾名思义,是基于所涉及对象的运行时类型,所以C#和VB.net 不要使用它,因为决定是正如您所说,在编译时制作。
【讨论】:
【参考方案7】:GoF 访问者模式是如何进行双重调度的示例。 Scott Meyers “更有效的 C++” 向您展示了如何在 C++ 中执行此操作。这是来自 Dobbs 博士的 link,它讨论了如何在 Java 和 C++ 中进行双重调度。
【讨论】:
【参考方案8】:我知道这是一个老问题..
在 .Net 4.0 中,您可以将 dynamic
关键字用于多种方法...请看下面的示例 .Net 4.0 Optimized code for refactoring existing "if" conditions and "is" operator
【讨论】:
以上是关于C# 是单调度语言还是多调度语言?的主要内容,如果未能解决你的问题,请参考以下文章