6

I have two classes.

Class A:

class A() {
    public void QQ() {}
    public void WW() {}
}

And Class B:

class B() {
    public void QQ() {}
    public void WW() {}
}

They don't share the same interface or abstract class. A and B have two distinct hierarcy and I can't change that at the moment.

I want to write a single procedute that works for A and B and use QQ and WW methods.

Can I do that? Can you suggest any document I can study?

Tanks

Hamid Pourjam
  • 20,441
  • 9
  • 58
  • 74
Admdebian
  • 630
  • 6
  • 17
  • 4
    you can use a delegate – Buda Gavril Dec 16 '15 at 08:23
  • it's very similar to dynamic type – Admdebian Dec 16 '15 at 08:35
  • "They don't share the same interface" - yes, currently there is no `interface` that they both implement. However, they clearly have some part of their public surface in common. So define an interface `ICanQQAndWW`, and have them both implement it. Why search for an ugly hack when there's already an obvious clean way to do it? – AakashM Dec 16 '15 at 08:47
  • Thank you all! I learned something new and different approaches – Admdebian Dec 16 '15 at 08:51

3 Answers3

8

This is called Duck Typing.

You can use dynamics

void Foo(dynamic dy)
{
    dy.QQ();
}

You can also use reflection. (reference)

public static void CallQQ(object o)
{
    var qq = o.GetType().GetMethod("QQ");
    if (qq != null)
        qq.Invoke(o, new object[] { });
    else
        throw new InvalidOperationException("method not found");
}
Community
  • 1
  • 1
Hamid Pourjam
  • 20,441
  • 9
  • 58
  • 74
  • 1
    This ignores the fact that the object dy may not have a QQ method, which would cause a runtime error. – Domysee Dec 16 '15 at 08:31
  • @Domysee I think this is better than hiding that fact in your approach – Ivan Stoev Dec 16 '15 at 08:33
  • @IvanStoev what do you mean? There is always the possibility to throw an exception if no type applies. – Domysee Dec 16 '15 at 08:44
  • Dear Downvoter. Care to comment? – Hamid Pourjam Dec 16 '15 at 08:46
  • 1
    @Domysee I mean that your method does nothing if you don't recognize the passed object type, thus hiding that fact from the caller. It should really throw exception, which will make it similar to this approach, but not so flexible. This answer is definitely better. +1 – Ivan Stoev Dec 16 '15 at 08:47
  • @IvanStoev Thanks for the explanation. I agree with you, this answer is more flexible and better adapts to change. – Domysee Dec 16 '15 at 08:58
4

You can check if the object is of the specific type, then cast it and invoke its method:

void InvokeQQ(object o){
    if(o is A)
        (o as A).QQ();
    if(o is B)
        (o as B).QQ();
}

In C#6 you can simplify this to

void InvokeQQ(object o){
    (o as A)?.QQ();
    (o as B)?.QQ();
}
Domysee
  • 12,718
  • 10
  • 53
  • 84
-1

Cant you just make a parent class and put these methods in it and then let A and B inherit from that class?

musab shaheed
  • 150
  • 1
  • 7
  • 2
    *"A and B have two distinct hierarcy and I can't change that at the moment."* – Domysee Dec 16 '15 at 08:41
  • can you explain your question in a little more detail? like do you want both of these methods to be called at the same time from a certain method in Main or somewhere? – musab shaheed Dec 16 '15 at 08:43
  • I have 2 classes with equal methods. The first is a production class and the latter is a test environment class. It's absurd I know. I have to write a code that works both in production and in test environment and I have to use those classes. – Admdebian Dec 16 '15 at 08:47