C#是单一调度语言还是多种调度语言?

问题描述 投票:30回答:8

我正试图了解什么是单次和多次调度。

我刚刚读过:http://en.wikipedia.org/wiki/Multiple_dispatch

从这个定义看来,C#和VB.Net是多次分派的,即使在编译时选择要调用的重载。

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

c# programming-languages multiple-dispatch single-dispatch
8个回答
40
投票

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

基本上,区别在于是在运行时还是编译时选择了要调用的方法。现在,我知道每个人都这么说,但是由于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


20
投票

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

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

void Main() {   
    IRebelAllianceShip theShip = new XWing();  
    CaptureSpaceShip((dynamic)theShip);
}

5
投票

C#是单派发,但有些博客帖子的标题似乎是他们在尝试模仿多种方法。如果我可以下载其中一篇文章,请在这里更新答案。


2
投票

C#不支持多调度。 “访问者设计”模式模拟的东西可以描述为多个调度,即使“访问者”模式主要集中于将算法与层次结构分开。


1
投票

根据cited Wikipedia article,根据定义,多重调度是基于所涉及对象的运行时类型的,所以C#和VB.net 不要使用它,因为您可以像状态,在编译时。


1
投票

也许有人会对使用动态关键字(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.

Wikipedia说C#4.0(动态)是“多调度”语言。我还认为Java,C#(4.0之前)和C ++等语言是单调度。

0
投票
GoF访客模式是如何执行双重调度的示例。 Scott Meyers的“更有效的C ++”向您展示了如何在C ++中实现它。这是Dobbs博士的link,讨论如何在Java和C ++中进行双重调度。

0
投票
我知道这是一个老问题。
© www.soinside.com 2019 - 2024. All rights reserved.