tags:

views:

391

answers:

4

I am confused by C# right now.

I have a bunch of classes, say A, B, and C, which all derive from class "Parent". I have a function which takes an argument of type Parent, and depending on which child class the object it is called with is, I want it to call a different method.

Currently, I am thinking using a dictionary mapping types to delegates, but that seems silly, though it is all I can come up with at the moment.

The problem is that when I am in the function, I only know that it is of type Parent, and I can use GetType to get which child class I have, which would allow the dictionary. Otherwise I would probably use function overloading.

Really typecasting seems like the best method, allowing me to use function overloading, which would be much less verbose, but I don't know how I could do it or if it would work at all.

Any reccomendations?

+5  A: 

Do the methods all share the same signature? If so, make it a virtual (potentially abstract) method in the parent class:

using System;

public abstract class Parent
{
    public abstract void DoSomething();
}

public class A : Parent
{
    public override void DoSomething()
    {
        Console.WriteLine("A.DoSomething()");
    }
}

public class B : Parent
{
    public override void DoSomething()
    {
        Console.WriteLine("B.DoSomething()");
    }
}

public class Test
{
    static void Main()
    {
        Parent a = new A();
        Parent b = new B();
        a.DoSomething();
        b.DoSomething();
    }
}

If this isn't suitable then double dispatch may be suitable, but I'd really need to know more about the situation... it could be that changing some part of the existing design would work better.

Jon Skeet
@Downvoter: Care to comment?
Jon Skeet
+2  A: 

This seems like a perfect use for the visitor pattern, if you can't add a virtual method to Parent, and override in A,B and C

Michael Donohue
Sure, if double dispatch is needed, but it's not clear whether it is. I'm guessing not.
Steven Sudit
I'm not suggesting double dispatch. Did you intend to comment on John Skeet's post?
Michael Donohue
The visitor pattern is double dispatch.
munificent
A: 

Is the name of the method different? Or is it a different implementation of the same method?

If the name of the method is the same, you can use override. Additionally, if there will only ever be a child method, the parent method should be marked abstract.

EDIT: with code...

public abstract class parentClass
{
    //...other stuff...
    protected abstract void doSomething(); //or use virtual instead of abstract and give the method a body
}

public class childClass : parentClass
{
    //...other stuff...
    protected override void doSomething()
    {
       //...do something
    }
}
McAden
A: 

Overloading is the correct way

public void DoWork(Parent obj)
{
   if(obj is A)
     Foo((A)obj);

   else if(obj is B)
     Foo((B)obj);

   else
    Foo(obj);
}

public void Foo(Parent obj)
{
  //Do something for parent
}

public void Foo(A obj)
{
  //Do something for A
}

public void Foo(B obj)
{
  //Do something for B
}

or if you don't want to explicitly cast the object for each type you could use reflection like this:

Bar methodObject = new Bar();
MethodInfo method = methodObject.GetType().GetMethod(
            "Foo", new Type[] { obj.GetType()});

method.Invoke(methodObject, new object[]{obj});
Brian Rudolph