Showing posts with label double dispatch. Show all posts
Showing posts with label double dispatch. Show all posts

Thursday, 23 May 2013

Overloading methods for derived classes

Using dynamic keyword to resolve double dispatch, overloaded methods using derived types at compile time.

image

using System;
using System.Collections.Generic;
using System.Reflection;

namespace OverloadedMethod
{
class Program
{
static void Main(string[] args)
{
var processor = new Processor();
var shapes = new List<Shape> {new Circle(), new Triangle()};

foreach (var shape in shapes)
{
// option 1
processor.GetType()
.GetMethod("Execute",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new[] { shape.GetType() },
null)
.Invoke(processor,
new object[] { shape });

// or option 2 (requires known definition of all drived types and a line per type)
if (shape is Circle) processor.Execute(shape as Circle);
else if (shape is Triangle) processor.Execute(shape as Triangle);

// option 3... BOOM!!!! Works a treat :)
processor.Execute(shape as dynamic);
}
}
}

class Shape { }

class Circle : Shape
{
public int Circumference { get { return 10; } }
}

class Triangle : Shape
{
public int HypotenuseLength { get { return 20; } }
}

class Processor
{
internal void Execute(Circle circle)
{
Console.WriteLine("Executing with a Circle with circumference {0}!", circle.Circumference);
}

internal void Execute(Triangle triangle)
{
Console.WriteLine("Executing with a Triangle hypotenuse length of {0}!", triangle.HypotenuseLength);
}
}
}


Source:  https://github.com/stevenh77/OverloadedMethod/


So what about this, using an extension method?  Apparently Circle doesn’t have a definition for Execute…


image


Source:  https://github.com/stevenh77/OverloadedMethodExtensions/

using System;
using System.Collections.Generic;

namespace OverloadedMethod
{
class Program
{
static void Main(string[] args)
{
var shapes = new List<Shape> {new Circle(), new Triangle()};

foreach (var shape in shapes)
{
// option 4: so what about this....?
// (shape as dynamic).Execute(); // doesn't work
ExtensionMethods.Execute(shape as dynamic); // this works!
}
}
}

class Shape { }

class Circle : Shape
{
public int Circumference { get { return 10; } }
}

class Triangle : Shape
{
public int HypotenuseLength { get { return 20; } }
}

static class ExtensionMethods
{
public static void Execute(this Circle circle)
{
Console.WriteLine("Executing with a Circle with circumference {0}!", circle.Circumference);
}

public static void Execute(this Triangle triangle)
{
Console.WriteLine("Executing with a Triangle hypotenuse length of {0}!", triangle.HypotenuseLength);
}
}
}