Double Dispatch in C#?

D

Dan Vogel

I'd like to find an elegant solution to the problem of calling a
certain function based on the types of two parameters. In my case,
the functions compute the distance between different types of
geometric objects, and I want to call the function that gives me the
most accurate distance.

I have a base class called Shape with basic functionality:

Shape

Then I have the following geometric types derived from Shape (not
always directly). Note I'm simplifying things here, not necessarily
the actual derived types:

Ellipse : Shape;
Circle : Ellipse;
Polyline : Shape;
BezierLine : Polygon;
Text : Shape;

Elsewhere in my code I have an ArrayList of Shapes, and I want to
compute the most accurate distance between any pair of shapes. Let's
say I call a static function called AccurateDistance:

distance = AccurateDistance(shape1, shape2)

I want this to select from a list of static functions that know how to
compute the most accurate distance between any combination of two
shapes:

Distance = Distance(Ellipse shape1, Polyline shape2)
Distance = Distance(Circle shape1, Text shape2)
Distance = Distance(BezierLine shape1, Polyline shape2)

etc ...


I know I could make a big switch statement, or do a bunch of if else
if clauses to dispatch to the best function based on the types of
shape1 and shape2 passed into AccurateDistance. But this seems
tedious and with more shapes added will become very difficult to
maintain. There must be a better solution to this problem. Perhaps
some way of adding the Distance calculation into the Shape classes
themselves? I thought about using delegates, but they need exactly
the same parameters in the param list don't they? Maybe someway of
using reflection?

Any help/ideas is much appreciated,

dan
 
W

Wayne

You could use delegates, passing Shape as the parameters. In each of your
methods assigned to the delegate do:

if (param1 is Ellipse && param2 is PolyLine) then
return calculation

so if you were to pass in a circle and a polyline the above code would just
go to the next method assigned to the delegate, if you pass in an ellipse
and polyline then the above code would calc your distance.

Thanks
Wayne
 
N

Nicholas Paldino [.NET/C# MVP]

Dan,

I think that you should have some methods on the base Shape class which
are overloaded which help you in the computation. As an example, lets
assume that the distance between two shapes is the distance between their
centers of gravity. Each shape, of course, would have a different center of
gravity.

Assuming each shape knows it's position, the base Shape class could have
a virtual property, CenterOfGravity, which returns a point (based on the
position) that indicates the center of gravity. Then, the static method
would be able to just call the properties to get the center of gravity and
calculate the distance.

The derived classes would then be responsible for providing an override
to indicate the center of gravity.

Hope this helps.
 
M

Michael Voss

Dan said:
I'd like to find an elegant solution to the problem of calling a
certain function based on the types of two parameters. In my case,
the functions compute the distance between different types of
geometric objects, and I want to call the function that gives me the
most accurate distance.

This sounds like double dispatch, as you mentioned in the header...
I have a base class called Shape with basic functionality:

Shape

Then I have the following geometric types derived from Shape (not
always directly). Note I'm simplifying things here, not necessarily
the actual derived types:

Ellipse : Shape;
Circle : Ellipse;
Polyline : Shape;
BezierLine : Polygon;
Text : Shape;

Elsewhere in my code I have an ArrayList of Shapes, and I want to
compute the most accurate distance between any pair of shapes. Let's
say I call a static function called AccurateDistance:

distance = AccurateDistance(shape1, shape2)

I want this to select from a list of static functions that know how to
compute the most accurate distance between any combination of two
shapes:

Why don't you implement a distanceTo(Shape target) instance method in each
Shape subclass like this (using real double dispatch):

class Circle
{
public float distanceTo(Shape target)
{
// Because we are in an instance of Circle, we know
// we have to calculate the distance to a circle,
// so we dispatch to the appropriate method of the target
return target.distanceToCircle(this);
}

public float distanceToText(Text text)
{
// Calculate the accurate distance between Circle and Text
return distance
}
}

class Text
{
public float distanceTo(Shape target)
{
// Because we are in an instance of Text, we know
// we have to calculate the distance to a text
// so we dispatch to the appropriate method of the target
return target.distanceToText(this);
}

publich float distanceToCircle(Circle circle)
{
// Calculate the accurate distance between Text and Circle
return distance
}
}

and so on.
The distanceToSomething(Something something) methods might be implemented in
the Shape class...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top