【问题标题】:Is C# a single dispatch or multiple dispatch language?C# 是单调度语言还是多调度语言?
【发布时间】:2010-10-03 13:20:15
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: c# programming-languages multiple-dispatch single-dispatch


    【解决方案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

              【讨论】:

                猜你喜欢
                • 2012-12-29
                • 2011-11-09
                • 1970-01-01
                • 1970-01-01
                • 2013-02-03
                • 2011-10-12
                • 2012-06-20
                • 2014-05-07
                相关资源
                最近更新 更多