Question

I have an object o which guaranteed at runtime to be one of three types A, B, or C, all of which implement a common interface I. I can control I, but not A, B, or C. (Thus I could use an empty marker interface, or somehow take advantage of the similarities in the types by using the interface, but I can't add new methods or change existing ones in the types.)

I also have a series of methods MethodA, MethodB, and MethodC. The runtime type of o is looked up and is then used as a parameter to these methods.

public void MethodA(A a) { ... }
public void MethodB(B b) { ... }
public void MethodC(C c) { ... }

Using this strategy, right now a check has to be performed on the type of o to determine which method should be invoked. Instead, I would like to simply have three overloaded methods:

public void Method(A a) { ... } // these are all overloads of each other
public void Method(B b) { ... }
public void Method(C c) { ... }

Now I'm letting C# do the dispatch instead of doing it manually myself. Can this be done? The naive straightforward approach doesn't work, of course:

Cannot resolve method 'Method(object)'. Candidates are:

  • void Method(A)
  • void Method(B)
  • void Method(C)
Was it helpful?

Solution

How about something like this?

private Dictionary<Type, Action<I>> _mapping = new Dictionary<Type, Action<I>>
{ 
  { typeof(A), i => MethodA(i as A)},
  { typeof(B), i => MethodB(i as B)},
  { typeof(C), i => MethodC(i as C)},
};

private void ExecuteBasedOnType(object value)
{
    if(_mapping.ContainsKey(value.GetType()))
       _mapping(value.GetType())(value as I);
}

OTHER TIPS

If you can refactor this, move the method to the interface and have each class has its implementation:

I i = o as I;
i.Method();

If the 3 class A, B and C implements the interface I you should do nothing. It's the runtime that choose the right method for you:

A a = new A();
class.Method(a); // will calll Method(A a)

B b = new B();
class.Method(b); // will call Method(B b)

I'm not 100% sure if this will work in your scenario, but it sounds like you might be able to use partial classes:

public interface IMethodCallable
{
    public void Method();
}

public partial class A : IMethodCallable
{
    public void Method()
    {
        ....
    }
}

then for the usage:

object o = getObject(); // we know this is A, B or C
((IMethodCallable)o).Method();

Preseumably O is declared as type/interface I then instantiated as either a b or c. The way to do it would be to have a single public method the took a param of type I and then do your logic within that method e.g. call private method A B or C.

Reading your edited post, o is of type object, remember to be clear when you take about an object becuase as well as being a c# type it is a generic oop term for an instance of a class.

Why are you declaring it as an object, rather than an i, might it be something else later?

If so to use your overloaded methods you would have to unbox it before calling the method. e.g.

if (o.GetType() == typeof(a))
{
   oa = (a)o;
   Method(oa);
}
else if(o.GetType() == typeof(b))
{
    ...
}

Etc.

Alternatively if you made the method take a paramater of type i you could do something like:

i oi = (i)o;
Method(oi);

But you would still need to do something like the the first example within your public method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top