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);
}
}
}

2 comments:

  1. Thanks, this is very informative and i think it's a very useful tips. I admire the time and effort you put into your well-detailed nice blog. I hope to see more of your write ups. Keep it up!!!

    ReplyDelete