30

我试图准确地理解单次和多次调度是什么。

我刚读到这个:
http ://en.wikipedia.org/wiki/Multiple_dispatch

从这个定义来看,在我看来,C# 和 VB.Net 是多调度的,即使在编译时选择调用哪个重载也是如此。

我在这里是正确的,还是我错过了什么?谢谢!

4

8 回答 8

47

好的,我理解函数重载与多次调度的细微差别。

基本上,区别在于调用哪个方法是在运行时还是编译时选择的。现在,我知道每个人都这么说,但没有一个明确的例子,这听起来很明显,因为 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

于 2009-01-27T14:42:51.930 回答
25

对于那些使用搜索引擎找到这篇文章的人,C# 4.0 引入了动态关键字。代码如下所示。

int CaptureSpaceShip(IRebelAllianceShip ship) {}
int CaptureSpaceShip(XWing ship) {}

void Main() {   
    IRebelAllianceShip theShip = new XWing();  
    CaptureSpaceShip((dynamic)theShip);
}
于 2011-06-14T15:42:38.467 回答
6

C# 是单一调度,但有一些博客文章的标题看起来像是在尝试模拟多方法。如果我可以加载其中一篇文章,我将在此处更新我的答案。

于 2009-01-26T14:29:32.160 回答
4

也许有人会对使用动态关键字进行多次调度的良好 C# 示例感兴趣( MSDN 博客

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++ 等语言是单调度的。

于 2015-01-18T11:56:17.007 回答
2

C# 不支持多分派。访问者设计模式模拟了可以描述为多次分派的东西,尽管访问者模式主要关注将算法与层次结构分离。

于 2009-01-26T14:38:25.433 回答
1

根据引用的 Wikipedia 文章,根据定义,多重分派是基于所涉及对象的运行时类型,因此 C# 和 VB.net使用它,因为正如您所说,在编译时做出决定.

于 2009-01-26T17:47:59.670 回答
0

GoF 访问者模式是如何进行双重调度的示例。Scott Meyers “更有效的 C++” 向您展示了如何在 C++ 中执行此操作。这是 Dobbs 博士的链接,讨论了如何在 Java 和 C++ 中进行双重调度。

于 2009-01-26T14:36:28.993 回答
0

我明白这是一个老问题..

在 .Net 4.0 中,您可以dynamic为多种方法使用关键字...请看下面的示例.Net 4.0 重构现有“if”条件和“is”运算符的优化代码

于 2014-01-22T14:13:03.720 回答