Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double dispatch in C#?

I have heard/read the term but don't quite understand what it means.

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

like image 957
Oded Avatar asked Sep 03 '08 21:09

Oded


People also ask

What is double dispatch in programming?

Double dispatch is a technical term to describe the process of choosing the method to invoke based both on receiver and argument types. A lot of developers often confuse double dispatch with Strategy Pattern. Java doesn't support double dispatch, but there are techniques we can employ to overcome this limitation.

What is double dispatch in visitor pattern?

In “double dispatch”, the operation executed depends on: the name of the request, and the type of TWO receivers (the type of the Visitor and the type of the element it visits). This essentially means different visitors can visit the same type and different types can be visited by the same visitor.

What is Dispatch in C?

When a user of a stack invokes a stack operation on the stack instance, the operation will dispatch to the corresponding operation in the vtable . This vtable is initialized by the creation function with the functions that correspond to its particular implementation.


2 Answers

The visitor pattern is a way of doing double-dispatch in an object-oriented way.

It's useful for when you want to choose which method to use for a given argument based on its type at runtime rather than compile time.

Double dispatch is a special case of multiple dispatch.

When you call a virtual method on an object, that's considered single-dispatch because which actual method is called depends on the type of the single object.

For double dispatch, both the object's type and the method sole argument's type is taken into account. This is like method overload resolution, except that the argument type is determined at runtime in double-dispatch instead of statically at compile-time.

In multiple-dispatch, a method can have multiple arguments passed to it and which implementation is used depends on each argument's type. The order that the types are evaluated depends on the language. In LISP, it checks each type from first to last.

Languages with multiple dispatch make use of generic functions, which are just function delcarations and aren't like generic methods, which use type parameters.

To do double-dispatch in C#, you can declare a method with a sole 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).     } }        
like image 53
Mark Cidade Avatar answered Oct 05 '22 16:10

Mark Cidade


The code posted by Mark isn't complete and what ever is there isn't working.

So tweaked 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 nice explanation on Double Dispatcher pattern.

like image 42
Zenwalker Avatar answered Oct 05 '22 16:10

Zenwalker