Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single/double dispatch via "dynamic overload" in C#

Why double dispatch via "dynamic overload" based on argument type isn't natively supported by C#? I see this would require dynamic dispatching but since virtual method calls are also dispatched dynamically this would not be that strange to the language. So why this feature is not part of C#? What would be most elegant solution to implement this functionality using Reflection (maybe there are some libraries)?

class Program
{
    static void Main(string[] args)
    {
        var objs = new object[] { new Class1(), new Class2() };
        foreach (var item in objs)
        {
            Method(item);
        }
    }

    static void Method(Class1 obj)
    {
    }

    static void Method(Class2 obj)
    {
    }
}

class Class1
{
}

class Class2
{
}

UPDATE indeed, because Method in this example isn't virtual and takes only one argument this would be still single dispatch but "cardinality" of dispatch isn't that important in this question as long as it's > 0.

like image 947
Pol Avatar asked Oct 01 '14 20:10

Pol


2 Answers

virtual is for single dispatch. If you need double dispatch, you could do this in C#:

var objs = new object[] { new Class1(), new Class2() };
foreach (var item in objs)
{
    Method((dynamic)item);
}

This will make the compiler interpret the call to your method in a very different way. It will emit a so-called call site which will determine at runtime which method should be called. This is also called late binding.

In this specific example you still get single dispatch, but it would have been double dispatch if Method were virtual.

This is very convenient to quickly implement the visitor pattern, but be aware that this will be slower than classic manual double-dispatch. So you may want to use the good old way in performance-sensitive code.

like image 197
Lucas Trzesniewski Avatar answered Sep 30 '22 05:09

Lucas Trzesniewski


Why double dispatch via "dynamic overload" based on argument type isn't natively supported by C#?

It is, via dynamic typing:

static void Main(string[] args)
{
    var objs = new object[] { new Class1(), new Class2() };
    // Note the change of type for item to "dynamic"
    foreach (dynamic item in objs)
    {
        Method(item);
    }
}

Operations involving a value with a compile-time type of dynamic are late-bound - so overload resolution is performed at execution-time, based on the actual type of the value. There's a lot more to dynamic typing than just overload resolution, of course, including types being able to provide members dynamically via code.

There's a performance hit for all of this - but sometimes it's the cleanest approach.

You may want to add an extra overload with a parameter of type object as a "catch-all" in case a value doesn't match either of the other overloads... although it would still be ambiguous if your array contains a null element.

like image 41
Jon Skeet Avatar answered Sep 30 '22 06:09

Jon Skeet