Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to tell apart overridden and hidden method?

Consider these variants:

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 returned results of the call typeof(B).GetMethod("Doit");

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



Update:

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

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



Update 2:

I googled about VtableLayoutMask and came back to StackOverflow

Udate 3:

resulting 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;
    }
}
like image 234
Pavel Voronin Avatar asked May 23 '14 09:05

Pavel Voronin


People also ask

Is method hiding and method overriding same?

For Method overriding override keyword is being used. In case of Method Hiding new keyword is used to define new implementation in child class. In Method Overriding the implementation type of the method is of object type. However on other hand implementation type of method in Method hiding is of reference type.

What is the difference between hiding and overriding?

Hiding redefines the complete method, whereas overriding redefines only the implementation of the method. In Overriding, you can access the base class using the child class' object overridden method.. Shadowing has cannot access the child class methods.

What is the difference between method hiding and method overriding explain with example?

In method overriding, when base class reference variable pointing to the object of the derived class, then it will call the overridden method in the derived class. In the method hiding, when base class reference variable pointing to the object of the derived class, then it will call the hidden method in the base class.

What is the difference between the new and override keywords when overriding a class method?

In C#, a method in a derived class can have the same name as a method in the base class. You can specify how the methods interact by using the new and override keywords. The override modifier extends the base class virtual method, and the new modifier hides an accessible base class method.


3 Answers

Update: The documentation seems to imply that IsHideBySig is the answer, but it does not appear to be the case in practice.

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, incorrect answer follows.

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

Note the above only applies to C# methods. The documentation elaborates with:

When a member in a derived class is declared with 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 base class members by signature. That is, if the base class member has multiple overloads, the only one that is hidden is the one that has the identical signature. By contrast, Visual Basic hides all the base class overloads. Thus, IsHideBySig returns false on a member declared with the Visual Basic Shadows modifier, and true on a member declared with the C# new modifier.

like image 76
Frédéric Hamidi Avatar answered Oct 07 '22 21:10

Frédéric Hamidi


The DeclaringType will be different if it was hidden with 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: A B
WillBeHidden: B B
WillBeInheritted: A A
WillBeHidden: A A
ToString: Object Object
Equals: Object Object
GetHashCode: Object Object
GetType: Object Object

WillBeInheritted has A as the declaring type for both the method and the base definition's declaring type.

WillBeOverridden has A for the base definition's declaring type, B for the declaring type.

WillBeHidden has two versions, the hidden one in A and the hiding one in B. This makes sense when we consider:

B b = new B();
A a = b;
b.WillBeHidden(); // calls hiding method.
a.WillBeHidden(); // calls hidden method on same object.
like image 40
Jon Hanna Avatar answered Oct 07 '22 19:10

Jon Hanna


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

For example if you let 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 instance mi represents the override as inherited (unchanged) to Giraffe. And mi.GetBaseDefinition() fetches another MethodInfo which represents instead the method Animal.M which does not carry the override keyword in the C# source.

like image 2
Jeppe Stig Nielsen Avatar answered Oct 07 '22 20:10

Jeppe Stig Nielsen