views:

242

answers:

2

The problem of single dispatch is mostly familiar to people engaged in coding with statically typed languages like Java and C#. The basic idea is:

While the runtime polymorphism allows us to dispatch to the right method call according to the type (runtime type) of receiver, for example:

IAnimal mything = new Cat();
mything.chop();

The method call will be performed according to the runtime type of mything, namely Cat. This is the single dispatch capability (which is present in Java/C#).

Now, if you need to dispatch not only on the runtime type of receiver, but on the types of (multiple) arguments either, you face a little problem:

public class MyAcceptor {  
    public void accept (IVisitor vst) {...}   
    public void accept (EnhancedConcreteVisitor vst) {...}  
}

The second method never gets called, because in our 'consumer' code we just tend to treat different types of objects (visitors in my example) by their common supertype or interface.

That's why I ask - because dynamic typing allows the multiple dispatch polymorphism and C# 4.0 has that dynamic keyword ;)

+1  A: 

Yes, you can create DLR types that do arbitrarily complex dispatch. Check out http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

Paul Betts
Thanks, I'll check just right now!
Bubba88
It seems that you have to write much code for that BTW :)
Bubba88
+7  A: 

Yes, dynamic typing allows multiple dispatch - and no, you don't have to create your own dynamic object to do it.

Suppose we wanted to implement Enumerable.Count() ourselves, and we didn't want a load of "if (source is IList)" tests in our code. We could write it like this:

public static class Enumerable
{
    public static int Count<T>(this IEnumerable<T> source)
    {
        dynamic d = source;
        return CountImpl(d);
    }

    private static int CountImpl<T>(ICollection<T> collection)
    {
        return collection.Count;
    }

    private static int CountImpl(ICollection collection)
    {
        return collection.Count;
    }

    private static int CountImpl<T>(string text)
    {
        return text.Length;
    }

    private static int CountImpl<T>(IEnumerable<T> source)
    {
        // Fallback
        int count = 0;
        foreach (T t in source)
        {
            count++;
        }
        return count;
    }
}

I'm not saying it would be a good idea, but that's how it would work :)

Note that you need to be careful not to introduce situations where you could end up with an ambiguous call for some types. This wouldn't be an issue using classes for parameters, but consider that a single class can implement multiple interfaces.

Jon Skeet
at the very least, a nice example for `dynamic`.
peterchen
Yep! That's what I was after) Big thanks for explanation and a little O_o to see Jon Skeet answer my question :)
Bubba88