Is it possible to distinguish between an overridden and hidden method?

Consider these options:

class A { public virtual void Doit() { } } class B : A { public new virtual void Doit() { } } 

or

 class B : A { public override virtual void Doit() { } } 

I cannot find the difference in the return results of typeof(B).GetMethod("Doit");

In both cases, MethodInfo.DecalringType is class B, and the other properties seem the same. Am I missing something or is there no way to distinguish them?



Update:

When I ran the sample in LINQPAd, I noticed a slight difference in the Attributes property:

for new virtual value was - PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask
for override - PrivateScope, Public, Virtual, HideBySig



Update 2:

I googled near VtableLayoutMask and went back to https://stackoverflow.com/a/312947/

Udate 3:

final code:

 public static class MethodInfoExtensions { public static bool IsOverriden(this MethodInfo method) { Contract.Requires<ArgumentNullException>(method != null, "method"); return method.IsVirtual && !method.IsStatic // overriden exactly in this class && method.ReflectedType == method.DeclaringType // not new and not declared for the first time in the class && method.GetBaseDefinition() != method; } } 
+7
reflection c #
source share
3 answers

DeclaringType will be different if it was hidden using new . For example, run:

 public class A { public virtual void WillBeInheritted() { } public virtual void WillBeOverridden() { } public virtual void WillBeHidden() { } } public class B : A { public override void WillBeOverridden() { } public virtual new void WillBeHidden() { } } class Program { public static void Main(string[] args) { foreach(var meth in typeof(B).GetMethods()) { Console.Write(meth.Name); Console.Write(": "); Console.Write(meth.GetBaseDefinition().DeclaringType.Name); Console.Write(" "); Console.WriteLine(meth.DeclaringType.Name); } Console.Read(); } } 

The output will be:

 WillBeOverridden: AB WillBeHidden: BB WillBeInheritted: AA WillBeHidden: AA ToString: Object Object Equals: Object Object GetHashCode: Object Object GetType: Object Object 

WillBeInheritted has A as the declaration type for both the method and the declaration type of the base definition.

WillBeOverridden has A for a basic definition declaring a type, B for a declaration type.

WillBeHidden has two versions, hidden in A and hidden in B This makes sense when you consider:

 B b = new B(); A a = b; b.WillBeHidden(); // calls hiding method. a.WillBeHidden(); // calls hidden method on same object. 
+2
source share

Update: The documentation implies that IsHideBySig is the answer, but in practice it does not look.

Another strategy is to rely on the presence of the NewSlot attribute:

 public static bool HasNewModifier(this MethodInfo method) { return (method.Attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.NewSlot; } 

Original, wrong answer follows.

You can rely on the IsHideBySig property. This will be true if the method has a new modifier.

Please note that this only applies to C # methods. Documentation is developed using:

When a member in a derived class is declared using the C # new modifier or the Visual Basic Shadows modifier, it can hide a member of the same name in the base class. C # hides elements of a signature base class. What if a member of the base class has several overloads, the only thing that is hidden is the one that has the same signature. In contrast, Visual Basic hides all overloads of the base class. Thus, IsHideBySig returns false in a member declared using the Visual Basic Shadows modifier and true for a member declared using the C # new modifier.

+4
source share

You can use GetBaseDefinition to find out where this method was first declared.

For example, if you give var mi = typeof(B).GetMethod("Doit"); , you can check if mi.GetBaseDefinition() == mi or if mi.GetBaseDefinition().DeclaringType == typeof(B) , etc.


Here is an example:

 class Animal : object { public virtual void M() { } } class Mammal : Animal { public override void M() { } } class Giraffe : Mammal { } static class Test { internal static void Run() { var mi = typeof(Giraffe).GetMethod("M"); Console.WriteLine(mi.ReflectedType); // Giraffe Console.WriteLine(mi.DeclaringType); // Mammal Console.WriteLine(mi.GetBaseDefinition().DeclaringType); // Animal } } 

The MethodInfo mi instance represents the override as inherited (unchanged) prior to Giraffe . And mi.GetBaseDefinition() retrieves another MethodInfo , which instead represents the Animal.M method, which does not carry the override keyword in the C # source.

+2
source share

All Articles