views:

2549

answers:

3

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?

+2  A: 

Double-dispatch is another name for the Visitor pattern.

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

Brad Wilson
+17  A: 

Example: 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.

Definition: 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).
    }
 }
Mark Cidade
Wonderful use of LINQ with reflection - I hadn't thought to apply it to those tedious xxxInfo objects before. Thanks!
Jarrod Dixon
I'm not so sure this is a great idea. This doesn't really implement double dispatch at all, I need to know *at compile-t* what the type of the thing is in order to specify the type parameter!! You may as well not bother with all the reflection code and simply cast the object. Am I missing something?
kronoz
It does implement double dispatch in that it's dispatching on both the runtime type of the object (derived from DoubleDispatch) and the method argument. The reflection on return type is used for extending the machanism to subclasses, so you can add "string Foo(string)" to a subclass and it'll work.
Mark Cidade
+2  A: 

I've been abstracting code that does what @marxidad wrote. You may find it useful.

http://jbazuzicode.blogspot.com/2008/12/double-dispatch-in-c.html

Jay Bazuzi