For example
BaseClass MyBase()
{
public int Add(BaseClass next)
{
if (this is InheritedA && next is InheritedA)
return 1;
The pattern you are implementing is called double virtual dispatch.
A single virtual dispatch chooses which method to call on the basis of the run-time type of the receiver and the compile time type of the arguments. This is a traditional virtual dispatch:
abstract class Animal {}
class Tiger : Animal {}
class Giraffe : Animal {}
class B
{
public virtual void M(Tiger x) {}
public virtual void M(Animal x) {}
}
class D : B
{
public override void M(Tiger x) {}
public override void M(Animal x) {}
}
...
B b = whatever;
Animal a = new Tiger();
b.M(a);
Which method is called? B.M(Tiger) and D.M(Tiger) are not chosen; we reject them based on the compile time type of the argument, which is Animal. But we choose whether to call B.M(Animal) or D.M(Animal) at runtime based on whether whatever is new B() or new D().
Double virtual dispatch chooses which method to call based on the runtime types of two things. If C# supported double virtual dispatch, which it does not, then the runtime dispatch would go to B.M(Tiger) or D.M(Tiger) even though the compile-time type of the argument is Animal.
C# 4 does however support dynamic dispatch. If you say
dynamic b = whatever;
dynamic a = new Tiger();
b.M(a);
Then the analysis of M will be done entirely at runtime using the runtime types of b and a. This is significantly slower, but it does work.
Alternatively, if you want to do double virtual dispatch and get as much analysis done at compile time as possible then the standard way to do that is to implement the Visitor Pattern, which you can look up on the internet easily.