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;
}
}
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.
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.
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.
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.
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 BasicShadows
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
returnsfalse
on a member declared with the Visual BasicShadows
modifier, andtrue
on a member declared with the C#new
modifier.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With