views:

408

answers:

8

Is it the same as overloading, if not, can you please provide and example of each in C#

I have read the responses to a similar question asked in SO ... i did not understand the responses posted to it.

Similar question asked here

EDIT: With the new "dynamic" keyword in C# 4.0 ... would this make the language "multi dispatch" enabled?

+1  A: 

Single / multiple dispatch are a kind of run-time overloading. Single dispatch is more commonly known as virtual functions. The exact function called when you call a virtual function is decided based on the run-time type of an object. Double dispatch is the same thing, extended to work with two objects - usually the this parameter and a second parameter. You can implement this without too much difficulty using the Vistor Pattern. Multiple dispatch further extends this concept to more parameters, but is significantly harder to implement in languages like C# (not that it can't be done, it's just hard). Some languages implement this ability right out of the box.

e.g. in .NET, the ToString() function is an example of single dispatch

// Single dispatch
Object o = GetSomeObject(); // Return SomeType casted to Object.
o.ToString(); // Call SomeType::ToString instead of just Object::ToString

// Double dispatch (this version won't work in C#)
Shape s1 = GetSquare();
Shape s2 = GetCircle();
s1.Intersects(s2); // If C# supported double dispatch, this would call Square::Intersects(Circle) not Square::Intersects(Shape)
Eclipse
+2  A: 

Multi-dispatch is related to method overloading but not the same. The former is a dynamic runtime decision, the latter is a static compiletime decision. There is implicitly a flexibility benefit, but a performance cost to multi-dispatch therefore.

AFAIK a language can support either, but not both, though both can be simulated (multi-dispatch can be simulated with visitors). C# determines datatypes at compile time and therefore is not a multi-dispatch language, so no examples are possible.

(caveat: I'm not 100% on this)


addendum: actually wikipedia has an article on this which seems pretty thorough, ooh and a helpful LISP example

annakata
With the new "dynamic" keyword in C# 4.0 ... would this make the language "multi dispatch" enabled?
Nick
@Nick, not exactly, but it would be pretty close.
configurator
exactly so I believe
annakata
ha - I knew I was uncomfortably far into Jon Skeet territory
annakata
+5  A: 

C# uses single dispatch, which includes overloaded methods. When you have the code

stringBuilder.Append(parameter);

the dispatcher looks at all methods defined on the stringBuilder's class, and finds the correct one.

For a multiple dispatch example, let's look at Prolog (which is the first one I could think of). You can define a function in prolog as such:

func(Arg1, Arg2) :- ....body....

This is not defined inside any class but in a global scope. Then, you can call func(Arg1, Arg2) on any two arguments and this function will be called. If you want something like overloading, you have to validate the argument types inside the function, and define it multiple times:

func(Arg1, Arg2) :- is_number(Arg1), is_string(Arg2), ....body....
func(Arg1, Arg2) :- is_string(Arg1), is_list(Arg2), ....body....
func(Arg1, Arg2) :- is_number(Arg1), is_list(Arg2), ....body....

Then, any two argument types you would send would both be checked - that is the multiple dispatch part.

In short, single dispatch only looks at methods defined on the first argument (in our first example, the stringBuilder), then resolves the correct overload to call using the other arguments. Multiple dispatch has methods/functions defined in the global scope and treats all arguments the same during overload resolution.

I hope I made myself clear, this is a pretty tough subject.


Update: I forgot to mention, multiple dispatch happens at runtime while single dispatch happens at compile time.
Update #2: Apparently, that was not true.

configurator
One of my favourite languages. Hope I got the predicates right though, I haven't used it for years.
configurator
Both single and multiple dispatch can be done at either compile time or runtime. Dynamic dispatch is the term for binding code at runtime.
Bill the Lizard
@Bill: yes, but the types used for multiple dispatch are the runtime types and the types used for single dispatch (for the arguments) are the compile time type. Am I mistaken here?
configurator
Yes you are mistaken. The single dispatch can be compile time only (the compiler knows the method is non virtual so emits a function call directly) or it emits code to change the function called depending on the runtime type of the variable to whom the message is being passed, normally via a vtable
ShuggyCoUk
+1  A: 

In OO languaes the text:

SomeType b;
a = b.Foo(c, d)

Means that the object b is being passed a message Foo with the parameters c and d. Single dispatch means that only ONE aspect of this system is responsible for determining at runtime which (of the possibly many) methods Foo will actually be called.

The model java, c# and most other OO languages use is that only the runtime type of 'b' gets to 'decide' what the actual method call is. So if you have a two implementations of SomeType both of which provide a different implementation of Foo then the decision as to which to use is based solely on which type b happens to be at that point. IF there are multiple overloads of Foo then the decision as to which overload to use is a compile time decision based solely on The compile time know types of b, c and d.

This then is single dispatch, the single point of choice is the type system associated with b.

Multiple Dispatch would, at runtime, allow the runtime types of b, c and d to decide which method to call (such a decision is inevitably more complex).

In a more dynamic system where the concept of well defined types is more fluid (say a system based on prototypes rather than the inheritance model you know from c++/java/C#) then the decision as to what method to invoke would instead be totally up to the actual instances b,c and d.

ShuggyCoUk
A: 
#include <iostream>

class Pet {
};

class Cat: public Pet {
};

class Dog: public Pet {
};

class Human {
};

class Man : public Human {
        public:
                void Kick(Cat& victim);
                void Kick(Dog& victim);
};

class Woman : public Human {
        public:
                void Kick(Cat& victim);
                void Kick(Dog& victim);
};

void Man::Kick(Cat& victim) {
        std::cout << "Meow!!!" << std::endl;
}

void Woman::Kick(Cat& victim) {
        std::cout << "I won't kick a cat" << std::endl;
}

void Man::Kick(Dog& victim) {
        std::cout << "I won't kick a dog" << std::endl;
}

void Woman::Kick(Dog& victim) {
        std::cout << "Woof!!!" << std::endl;
}

int main(int argc, char** argv) {
        Man kicker;
        Dog victim;
        Pet zoo[] = { victim };
        kicker.Kick(victim);
//      kicker.Kick(zoo[0]);   // No multimethods
        return 0;
}

As for now, C++ cannot figure out at runtime whether a Pet is actually a Cat or a Dog.

If there were some way to do it at runtime (so that the code above would compile with the commented line uncommented), C++ would be said to support multiple dispatch, or multimethods.

Quassnoi
+1  A: 

Multiple dispatch is a "form" of overloading...

For example, C# is single dispatch because if works out what method to call based on only one argument, the "this" pointer. When you have something like this:

Base base=new Derived();
base.DoSomething();

the method Derived.DoSomething is called even though you called it through the base pointer. Now, if we've got the following:

class Derived : Base
{
  public override void Process(Stream stream);
  public override void Process(FileStream stream);
  public override void Process(MemoryStream stream);
}

And we do this:

Stream stream=new MemoryStream(...);
Base b=new Derived();
b.Process(stream);

Then we will call the Process(Stream) method as C# does a single dispatch on the object pointer (b) and then uses the compile time information to decide which method to call. Even though stream is a MemoryStream a single dispatch system will ignore this.

In a multi-dispatch system the object pointer will be looked at (as in C#) AND the runtime types of the arguments will be examined. In the above example, because stream is actually a MemoryStream the system would call the Process(MemoryStream) method.

Sean
While the explanation is correct, there's an error in the code; b.Process cannot be called if it only defined in Derived.
configurator
A: 

In c# 4.0 multimethods are enabled with the new dynamic keyword:

using System; namespace Example { class Wheel { public void RepairWhell() { } }

class Chassis
{
    public void RepairChassis() { }
}

class Engine
{
    public void RepairEngine() { }
}

class CarWorkshop
{
    public string Repair(Wheel value)
    {
        value.RepairWhell();
        return "wheel repaired";
    }
    public string Repair(Chassis value)
    {
        value.RepairChassis();
        return "chassis repaired";
    }
    public string Repair(Engine value)
    {
        value.RepairEngine();
        return "engine repaired";
    }
}

class Program
{
    static void Main(string[] args)
    {
        dynamic carWorkshop = new CarWorkshop();

        var whell = new Wheel();
        var chassis = new Chassis();
        var engine = new Engine();

        Console.WriteLine(carWorkshop.Repair(whell));
        Console.WriteLine(carWorkshop.Repair(chassis));
        Console.WriteLine(carWorkshop.Repair(engine));
        Console.ReadLine();
    }
}

}

Dynamic introduce multimethods, a very powerfull paradigm, in c#.

A: 

Sorry, the example I give before it's mistaken. Thas't the correct version:

class Wheel
{
    public void RepairWhell() { }
}

class Chassis
{
    public void RepairChassis() { }
}

class Engine
{
    public void RepairEngine() { }
}

class CarWorkshop
{
    public string Repair(Wheel value)
    {
        value.RepairWhell();
        return "wheel repaired";
    }
    public string Repair(Chassis value)
    {
        value.RepairChassis();
        return "chassis repaired";
    }
    public string Repair(Engine value)
    {
        value.RepairEngine();
        return "engine repaired";
    }
}

class Program
{
    static void Main(string[] args)
    {
        var carWorkshop = new CarWorkshop();

        dynamic whell = new Wheel();
        dynamic chassis = new Chassis();
        dynamic engine = new Engine();

        Console.WriteLine(carWorkshop.Repair(whell));
        Console.WriteLine(carWorkshop.Repair(chassis));
        Console.WriteLine(carWorkshop.Repair(engine));
        Console.ReadLine();
    }
}

So the anwer it's yes. C# provides multi dispatch.