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# 是单调度语言还是多调度语言?的主要内容,如果未能解决你的问题,请参考以下文章

c语言多线程线程不执行的原因

golang和swoole区别

自用纯C语言实现任务调度(可用于STM32C51等单片机)

怎么用C语言实现多级反馈队列调度算法?

急求 程序代码 c/c++ 操作系统中的 处理机调度算法

2021-GO语言并发编程