在C#中双派遣?

我曾经听过/读过这个词,但不太明白它的含义。

我应该什么时候使用这种技术,我将如何使用它? 任何人都可以提供一个好的代码示例

访问者模式是以面向对象的方式进行双向调度的一种方式。

当你想在运行时根据typesselect使用哪种方法而不是编译时,这是非常有用的。

双派遣是多派遣的特例。

当你在一个对象上调用一个虚拟方法时,这被认为是单调度的,因为调用的是实际的方法取决于单个对象的types。

对于双重调度,对象的types和方法唯一参数的types都被考虑在内。 这就像方法重载parsing一样,只是参数types是在运行时在双重调度时确定的,而不是在编译时静态确定的。

在multi-dispatch中,一个方法可以有多个parameter passing给它,而使用哪个实现取决于每个参数的types。 types的评估顺序取决于语言。 在LISP中,它从头到尾检查每种types。

具有多次调度的语言使用generics函数,这些generics函数只是函数定义,并不像使用types参数的generics方法。

要在C#中执行双重调度 ,您可以声明一个唯一对象参数的方法,然后声明具有特定types的特定方法:

using System.Linq; class DoubleDispatch { public T Foo<T>(object arg) { var method = from m in GetType().GetMethods() where m.Name == "Foo" && m.GetParameters().Length==1 && arg.GetType().IsAssignableFrom (m.GetParameters()[0].GetType()) && m.ReturnType == typeof(T) select m; return (T) method.Single().Invoke(this,new object[]{arg}); } public int Foo(int arg) { /* ... */ } static void Test() { object x = 5; Foo<int>(x); //should call Foo(int) via Foo<T>(object). } } 

那么嘿家伙,由马克张贴的代码是不完整的,什么都没有工作。

所以调整和完成。

 class DoubleDispatch { public T Foo<T>(object arg) { var method = from m in GetType().GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) where m.Name == "Foo" && m.GetParameters().Length == 1 //&& arg.GetType().IsAssignableFrom // (m.GetParameters()[0].GetType()) &&Type.GetType(m.GetParameters()[0].ParameterType.FullName).IsAssignableFrom(arg.GetType()) && m.ReturnType == typeof(T) select m; return (T)method.Single().Invoke(this, new object[] { arg }); } public int Foo(int arg) { return 10; } public string Foo(string arg) { return 5.ToString(); } public static void Main(string[] args) { object x = 5; DoubleDispatch dispatch = new DoubleDispatch(); Console.WriteLine(dispatch.Foo<int>(x)); Console.WriteLine(dispatch.Foo<string>(x.ToString())); Console.ReadLine(); } } 

感谢Mark和其他人对Double Dispatcher模式的很好的解释

Double-dispatch是Visitor模式的另一个名称。

我有一篇文章是我几年前写的关于使用Reflection来实现Visitor模式的。 http://www.agileprogrammer.com/dotnetguy/articles/ReflectionVisitor.aspx

C#4引入了在运行时(而不是编译时)parsing函数调用的伪typesdynamic 。 (也就是说,使用expression式的运行时types)。 双(或多发)可以简化为:

 class C { } static void Foo(C x) => Console.WriteLine(nameof(Foo)); static void Foo(object x) => Console.WriteLine(nameof(Object)); public static void Main(string[] args) { object x = new C(); Foo((dynamic)x); // prints: "Foo" Foo(x); // prints: "Object" } 

尽pipe整体types要小心。 由于dynamic被视为System.Object它将永远不会在上面的例子中调用void Foo(int x)

还要注意,通过使用dynamic您可以防止编译器使用静态分析器来检查这部分代码。 你应该仔细考虑使用dynamic

Interesting Posts