Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if virtual method is overridden in c# [duplicate]

Is it possible to determine if a virtual method has been overridden:

class ABase {

  public void DoSomething(object p)
  {
    p.Process();
    if( /* DoSomethingExtra is implemented */ )
      DoSomethingExtra(p);
  }
  public virtual void DoSomethingExtra(object p) { }

}

class ADerived {
  public override void DoSomethingExtra(object p)
  {
    p.ProcessMore();
  }
}

I realize that this example seems stupid (e.g. why don't you just call DoSomethingExtra() since it doesn't do anything). I assure you I have a legitimate case for this. Any ideas?

like image 737
Trevor Avatar asked Aug 29 '11 18:08

Trevor


4 Answers

Reflection is a good answer to this question.

using System.Reflection;

Type classType = typeof(ADerived);
MethodInfo method = classType.GetMethod("DoSomethingExtra");
if (method.DeclaringType == typeof(ABase))
    Console.WriteLine("DoSomethingExtra not overridden.");
else
    Console.WriteLine("DoSomethingExtra is overridden by " + method.DeclaringType.Name);

I hope that you will find this usefull.

Once I were implementing a special object viewer, when the object was unknown I would use ToString() unless it was not overridden.

like image 66
Casperah Avatar answered Oct 16 '22 18:10

Casperah


This is the simplest way to get what you want:

var isDerived = typeof(ADerived).GetMember("DoSomethingExtra", 
                   BindingFlags.NonPublic 
                 | BindingFlags.Instance 
                 | BindingFlags.DeclaredOnly).Length == 0;

Update: The link provided here is more verbose than necessary, but is also incomplete. The version above will also work for protected methods and virtual properties (That's why you use GetMember instead of the more restrictive GetMethod), neither of which the link addresses.

like image 20
Michael Hays Avatar answered Sep 28 '22 03:09

Michael Hays


So in C# it is possible to declare a virtual method without implementing it.

This is not possible. You can declare a method as abstract, but if the method is virtual, it will have some implementation (even if the implementation is effectively a null op).

Your code above reports the error Error 1 'ABase.DoSomethingExtra(object)' must declare a body because it is not marked abstract, extern, or partial.

The typical way to handle this is to just declare the method with a null op implementation, and call it:

class ABase {
  public void DoSomething(object p)
  {
    p.Process();
    DoSomethingExtra(p); // Always call
  }
  public virtual void DoSomethingExtra(object p)
  {
      // Do nothing here
  }
}

Edit: Now that your question has been edited, I'll give you more information related to your edit, in particular, this:

I realize that this example seems stupid (e.g. why don't you just call DoSomethingExtra() since it doesn't do anything). I assure you I have a legitimate case for this. Any ideas?

There is no direct way to determine whether the current instance has overriden your virtual method. This would likely require some pretty nasty, unmaintainable code, such as checking the method body declaring type via reflection to see what is there.

That being said, I would strongly question the design goal here. Your question is basically asking for a specific way to violate the Liskov Substitution Principle, which is one of the core principles in object oriented programming. This is going to have the effect of making your code less performant and much less maintainable...

like image 10
Reed Copsey Avatar answered Oct 16 '22 17:10

Reed Copsey


Check this out: Detect if a method was overridden using Reflection (C#)

Reflection would be the only way to do this at runtime. This should come with a health warning however, it should be considered a Very Bad Idea™ from an OOP perspective. A base class should not generally know or care how a derived class is implemented.

like image 3
James Gaunt Avatar answered Oct 16 '22 19:10

James Gaunt