什么是单次调度和多次调度(与 .NET 相关)?
它是否与重载相同,如果不是,您能否提供 C# 中每个问题的示例
我已经阅读了对 SO 中提出的类似问题的答复...我不明白发布到它的答复。
类似的问题此处
提出编辑:使用新的“动态” C# 4.0 中的关键字...这会使语言“多重调度”启用吗?
Is it the same as overloading, if not, can you please provide and example of each in C#
I have read the responses to a similar question asked in SO ... i did not understand the responses posted to it.
Similar question asked here
EDIT: With the new "dynamic" keyword in C# 4.0 ... would this make the language "multi dispatch" enabled?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
多重分派是重载的一种“形式”...
例如,C# 是单分派,因为如果仅根据一个参数(“this”指针)计算出要调用的方法。 当你有这样的事情时:
即使你通过基指针调用方法 Derived.DoSomething 也会被调用。 现在,如果我们有以下内容:
我们这样做:
然后我们将从
Derived
调用 Process(Stream) 方法,就像 C# 对对象执行一次调度一样指针(b),然后使用编译时信息来决定调用哪个方法。 即使stream是一个MemoryStream,单个调度系统也会忽略这一点。在多调度系统中,将查看对象指针(如在 C# 中)并且将检查参数的运行时类型。 在上面的示例中,由于stream实际上是MemoryStream,因此系统将调用Process(MemoryStream)方法。
Multiple dispatch is a "form" of overloading...
For example, C# is single dispatch because if works out what method to call based on only one argument, the "this" pointer. When you have something like this:
the method Derived.DoSomething is called even though you called it through the base pointer. Now, if we've got the following:
And we do this:
Then we will call the Process(Stream) method from
Derived
as C# does a single dispatch on the object pointer (b) and then uses the compile time information to decide which method to call. Even though stream is a MemoryStream a single dispatch system will ignore this.In a multi-dispatch system the object pointer will be looked at (as in C#) AND the runtime types of the arguments will be examined. In the above example, because stream is actually a MemoryStream the system would call the Process(MemoryStream) method.
C# 使用单一调度,其中包括重载方法。 当您拥有代码时,
调度程序会查看 stringBuilder 类中定义的所有方法,并找到正确的方法。
对于多重分派示例,让我们看一下 Prolog(这是我能想到的第一个)。 您可以在序言中定义一个函数,如下所示:
这不是在任何类内部定义的,而是在全局范围内定义的。 然后,您可以对任意两个参数调用 func(Arg1, Arg2) ,并且该函数将被调用。 如果你想要重载之类的东西,你必须验证函数内的参数类型,并多次定义它:
然后,你要发送的任何两个参数类型都将被检查 - 这就是多重分派部分。
简而言之,单一调度仅查看第一个参数(在我们的第一个示例中为 stringBuilder)上定义的方法,然后解析正确的重载以使用其他参数进行调用。 多重分派具有在全局范围内定义的方法/函数,并在重载决策期间将所有参数视为相同。
我希望我已经说清楚了,这是一个非常困难的话题。
更新:我忘了提及,多重分派发生在运行时,而单分派发生在编译时。更新#2:显然,这不是真的。
C# uses single dispatch, which includes overloaded methods. When you have the code
the dispatcher looks at all methods defined on the stringBuilder's class, and finds the correct one.
For a multiple dispatch example, let's look at Prolog (which is the first one I could think of). You can define a function in prolog as such:
This is not defined inside any class but in a global scope. Then, you can call
func(Arg1, Arg2)
on any two arguments and this function will be called. If you want something like overloading, you have to validate the argument types inside the function, and define it multiple times:Then, any two argument types you would send would both be checked - that is the multiple dispatch part.
In short, single dispatch only looks at methods defined on the first argument (in our first example, the stringBuilder), then resolves the correct overload to call using the other arguments. Multiple dispatch has methods/functions defined in the global scope and treats all arguments the same during overload resolution.
I hope I made myself clear, this is a pretty tough subject.
Update: I forgot to mention, multiple dispatch happens at runtime while single dispatch happens at compile time.Update #2: Apparently, that was not true.
多重调度与方法重载有关,但又不一样。 前者是动态运行时决定,后者是静态编译时决定。 多重调度隐含着灵活性优势,但也会带来性能成本。
据我所知,一种语言可以支持其中之一,但不能同时支持两者,尽管两者都可以模拟(可以与访问者模拟多调度)。 C# 在编译时确定数据类型,因此不是多调度语言,因此无法提供示例。
(警告:我对此不是 100%)
附录:实际上维基百科有一个 文章 看起来相当详尽,哦,还有一个有用的 LISP 示例
Multi-dispatch is related to method overloading but not the same. The former is a dynamic runtime decision, the latter is a static compiletime decision. There is implicitly a flexibility benefit, but a performance cost to multi-dispatch therefore.
AFAIK a language can support either, but not both, though both can be simulated (multi-dispatch can be simulated with visitors). C# determines datatypes at compile time and therefore is not a multi-dispatch language, so no examples are possible.
(caveat: I'm not 100% on this)
addendum: actually wikipedia has an article on this which seems pretty thorough, ooh and a helpful LISP example
在 OO 语言中,文本:
表示正在向对象 b 传递带有参数 c 和 d 的消息 Foo。
单一调度意味着该系统只有一个方面负责在运行时确定 Foo 方法(可能有很多方法中的哪一个)将被实际调用。
java、c# 和大多数其他 OO 语言使用的模型是,只有“b”的运行时类型才能“决定”实际的方法调用是什么。 因此,如果您有 SomeType 的两个实现,它们都提供了 Foo 的不同实现,那么使用哪个的决定仅基于此时 b 恰好属于哪种类型。 如果 Foo 有多个重载,那么使用哪个重载的决定是编译时决定,仅基于编译时知道 b、c 和 d 的类型。
这就是单次调度,单点选择是与 b 关联的类型系统。
Multiple Dispatch 将在运行时允许 b、c 和 d 的运行时类型决定调用哪个方法(这样的决定不可避免地会更加复杂)。
在一个更加动态的系统中,明确定义的类型的概念更加灵活(比如基于原型的系统,而不是您从 c++/java/C# 中了解的继承模型),那么调用什么方法的决定将完全取决于到实际实例 b、c 和 d。
In OO languaes the text:
Means that the object b is being passed a message Foo with the parameters c and d.
Single dispatch means that only ONE aspect of this system is responsible for determining at runtime which (of the possibly many) methods Foo will actually be called.
The model java, c# and most other OO languages use is that only the runtime type of 'b' gets to 'decide' what the actual method call is. So if you have a two implementations of SomeType both of which provide a different implementation of Foo then the decision as to which to use is based solely on which type b happens to be at that point. IF there are multiple overloads of Foo then the decision as to which overload to use is a compile time decision based solely on The compile time know types of b, c and d.
This then is single dispatch, the single point of choice is the type system associated with b.
Multiple Dispatch would, at runtime, allow the runtime types of b, c and d to decide which method to call (such a decision is inevitably more complex).
In a more dynamic system where the concept of well defined types is more fluid (say a system based on prototypes rather than the inheritance model you know from c++/java/C#) then the decision as to what method to invoke would instead be totally up to the actual instances b,c and d.
单/多调度是一种运行时重载。 单一调度通常称为虚拟函数。 调用虚函数时具体调用的函数是根据对象的运行时类型决定的。 双重调度是同样的事情,扩展为使用两个对象 - 通常是
this
参数和第二个参数。 您可以使用访问者模式轻松实现此目的。 多重分派进一步将此概念扩展到更多参数,但在 C# 等语言中实现起来要困难得多(不是说它不能做到,只是很难)。 有些语言直接实现了这种能力。例如,在 .NET 中,ToString() 函数是单次调度的一个示例
Single / multiple dispatch are a kind of run-time overloading. Single dispatch is more commonly known as virtual functions. The exact function called when you call a virtual function is decided based on the run-time type of an object. Double dispatch is the same thing, extended to work with two objects - usually the
this
parameter and a second parameter. You can implement this without too much difficulty using the Vistor Pattern. Multiple dispatch further extends this concept to more parameters, but is significantly harder to implement in languages like C# (not that it can't be done, it's just hard). Some languages implement this ability right out of the box.e.g. in .NET, the ToString() function is an example of single dispatch
目前,C++ 无法在运行时判断
Pet
实际上是Cat
还是Dog
。如果有某种方法可以在运行时执行此操作(以便上面的代码可以在注释行未注释的情况下进行编译),则可以说 C++ 支持多重分派或多方法。
As for now, C++ cannot figure out at runtime whether a
Pet
is actually aCat
or aDog
.If there were some way to do it at runtime (so that the code above would compile with the commented line uncommented), C++ would be said to support multiple dispatch, or multimethods.
在 c# 4.0 中,使用新的动态关键字启用了多种方法:
using System;
命名空间示例
{
类轮
{
公共无效RepairWhell(){}
。
在 C# 中动态
引入多方法,这是一个非常强大的范例
In c# 4.0 multimethods are enabled with the new dynamic keyword:
using System;
namespace Example
{
class Wheel
{
public void RepairWhell() { }
}
}
Dynamic introduce multimethods, a very powerfull paradigm, in c#.
抱歉,我之前举的例子有误。 这不是正确的版本:
所以答案是肯定的。 C# 提供多调度。
Sorry, the example I give before it's mistaken. Thas't the correct version:
So the anwer it's yes. C# provides multi dispatch.
您可以使用dynamic关键字在C#中实现多调度。
Foo((dynamic)a,(dynamic)b)) 的解析是在运行时完成的,并根据 'a' 和 'b' 的具体类型选择重载的 Foo 方法之一。
You can use the dynamic keyword to implement multi-dispatch in C#.
The resolution of Foo((dynamic)a,(dynamic)b)) is done at runtime, and selects one of the overloaded Foo methods based on the concrete types of 'a' and 'b'.