Duplicate in C #?

I have heard / read the term, but do not quite understand what this means.

When should I use this technique and how to use it? Can someone provide a good sample code?

+55
c # design-patterns language-features double-dispatch
Sep 03 '08 at 21:03
source share
4 answers

A visitor template is a way to make duplicate submission in an object-oriented manner.

This is useful when you want to choose which method to use for a given argument based on its type at runtime rather than compilation time.

Double sending is a special case of sending multiple messages .

When you call a virtual method on an object that is considered unidirectional, because the actual method being called depends on the type of one object.

For double sending, the type of the object and the type of the only method method are taken into account. This is similar to allowing method overloads, except that the type of the argument is determined at runtime in dual dispatch instead of statically at compile time.

When sending multiple times, a method can have several arguments passed to it, and which implementation is used depends on each type of argument. The type evaluation procedure is language dependent. In LISP, it checks each type from first to last.

Languages ​​with multiple dispatchers use common functions that are simply functions of decartation and do not look like general methods that use type parameters.

To do double dispatch in C # , you can declare a method with a single object argument, and then specific methods with specific 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). } } 
+52
Sep 03 '08 at 21:38
source share

Well guys, the code posted by Mark is not complete, and something doesn't work there.

So changed and complete.

 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(); } } 

Thanks Mark and others for a good explanation on the Double Dispatcher pattern.

+11
Jun 08
source share

Duplicate is another name for Visitor Template .

I have an article I wrote a few years ago about using Reflection to implement a Visitor template. http://www.agileprogrammer.com/dotnetguy/articles/ReflectionVisitor.aspx

+1
Sep 03 '08 at 21:05
source share

In C # 4, the dynamic pseudo-type is introduced, which allows a function to be called at run time (instead of compilation time). (That is, the type of execution time of the expression is used). Dual (or multidirectional) can be simplified to:

 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" } 

Be careful though with built-in types. Since dynamic treated as System.Object , it will never call void Foo(int x) in the above example.

Also note that with dynamic you prevent the compiler from using static analyzers to learn this part of the code. You should carefully consider using dynamic .

0
Jul 12 '17 at 9:29
source share



All Articles