Is there any way to call the parent version of an overridden method? (C# .NET)
Solution 1
At the IL level, you could probably issue a call
rather than a callvirt
, and get the job done - but if we limit ourselves to C# ;-p (edit darn! the runtime stops you: VerificationException
: "Operation could destabilize the runtime."; remove the virtual
and it works fine; too clever by half...)
Inside the ChildClass
type, you can use base.methodTwo()
- however, this is not possible externally. Nor can you go down more than one level - there is no base.base.Foo()
support.
However, if you disable polymorphism using method-hiding, you can get the answer you want, but for bad reasons:
class ChildClass : ParentClass
{
new public int methodTwo() // bad, do not do
{
return 2;
}
}
Now you can get a different answer from the same object depending on whether the variable is defined as a ChildClass
or a ParentClass
.
Solution 2
Inside of ChildClass.methodTwo()
, you can call base.methodTwo()
.
Outside of the class, calling ((ParentClass)a).methodTwo()
will call ChildClass.methodTwo
. That's the whole reason why virtual methods exist.
Solution 3
As mentioned above, something is bad with your class design if you need to call "base.base" in PRODUCTION code. But it is quite legitimate to use this technique if you are debugging or searching some workarrounds while using external libraries you cannot compile. It is unpleasant that C# does not provide this option directly. Still you may use Kenneth Xu solution with IL generator and Emit. It works.
class A { public virtual string foo() { return "A"; } }
class B : A { public override string foo() { return "B"; } }
// now in class C
class C : B {}
// we can call virtual method "foo" from A using following code
MethodInfo fooA = typeof(A).GetMethod("foo", BindingFlags.Public | BindingFlags.Instance);
DynamicMethod baseBaseFoo = new DynamicMethod(
"foo_A",
typeof(string),
new[] { typeof(A) },
typeof(A));
ILGenerator il = baseBaseFoo.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.EmitCall(OpCodes.Call, fooA, null);
il.Emit(OpCodes.Ret);
// call foo() from class A, it returns "A"
(string)baseBaseFoo.Invoke(null, new object[] { this });
For reference and a complete sample see http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html
Thank you Kenneth Xu!
Solution 4
public class Parent
{
public string Method()
{
return "parent";
}
}
public class Child:Parent
{
public string Method()
{
return "child";
}
}
Above code successfully overrides parent method yet value of parent method still unchanged.
You can return values from the Both Parent class and Child class using code below -
Child child = new Child();
string result = (((Parent)child).Method()) + child.Method();
But Visual Studio will show you a warning in Compile Time.
Solution 5
As Mark Gravell said, no, not externally. But here's another hack I have used. ChildClass
can expose methodTwo()
from the ParentClass
for its own use or for external use. In your case:
class ChildClass : ParentClass {
override public int methodTwo() {
return 2;
}
public int ParentClass_methodTwo() {
return base.methodTwo();
}
}
// Now instead of
Console.WriteLine("ParentClass methodTwo: " + ((ParentClass)a).methodTwo());
// use
Console.WriteLine("ParentClass methodTwo: " + a.ParentClass_methodTwo());
In my case, the child class introduced the concept of a Peer, and I needed its override of methodTwo()
to invoke the base version on the peer. By overridding it, however, it hid it... Or did it? This technique came to the rescue.
class ChildClass : ParentClass {
ChildClass peer;
override public int methodTwo() {
return peer.ParentClass_methodTwo();
}
private int ParentClass_methodTwo() {
return base.methodTwo();
}
}
Related videos on Youtube
Comments
-
Jader Dias almost 2 years
In the code below I tried in two ways to access the parent version of methodTwo, but the result was always 2. Is there any way to get the 1 result from a ChildClass instance without modifying these two classes?
class ParentClass { public int methodOne() { return methodTwo(); } virtual public int methodTwo() { return 1; } } class ChildClass : ParentClass { override public int methodTwo() { return 2; } } class Program { static void Main(string[] args) { var a = new ChildClass(); Console.WriteLine("a.methodOne(): " + a.methodOne()); Console.WriteLine("a.methodTwo(): " + a.methodTwo()); Console.WriteLine("((ParentClass)a).methodTwo(): " + ((ParentClass)a).methodTwo()); Console.ReadLine(); } }
Update ChrisW posted this:
From outside the class, I don't know any easy way; but, perhaps, I don't know what happens if you try reflection: use the Type.GetMethod method to find the MethodInfo associated with the method in the ParentClass, and then call MethodInfo.Invoke
That answer was deleted. I'm wondering if that hack could work, just for curiosity.
-
ivan_pozdeev about 10 yearsThe reflection trick doesn't work, it calls the child's method too.
-
Byte Commander about 8 yearsPossible duplicate of How can I call the 'base implementation' of an overridden virtual method?
-
-
Andrew Hare over 15 yearsThis is not a bad answer - I think he meant you can't call the overriden parent method from an instance of the child, which was the spirit of the question.
-
Michael Meadows over 15 years.., and -1 for all the ways it gets overused/misused.
-
Andrew Hare over 15 yearsMichael - you downvoted someones explanation of polymorphic behavior? Craig was simply explaining why things work the way that they do, don't flail about downvoting good answers simply because they explain a concept you happen to believe is overused.
-
Kevin Gauthier over 15 yearsI'm guessing he was joking. :)
-
Michael Meadows over 15 yearsdidn't downvote. just wanted to throw in my -1 cent on the overuse of polymorphism. Sorry if that wasn't clear.
-
Jan Doggen almost 9 yearsPlease edit your answer and include the essentials. Your answer is in another castle.
-
Ananda G about 8 yearsDo you have a references, It would be better if u do.
-
Peter Huber almost 7 yearsWhy is using "new" bad in this case ? Is there any case where using "new" is good ?
-
Marc Gravell almost 7 years@PeterHuber because it breaks polymorphism; the main use-case for
new
in this scenario is for making a type more specialized. For example,DbCommand
has apublic DbParameterCollection Parameters {get;}
- butSqlCommand : DbCommand
has apublic new SqlParameterCollection Parameters {get;}
. Both APIs return the same instance (achieved by a separateprotected abstract
property, namelyDbParameterCollection
- so the value will always be aSqlParameterCollection
) - but the more-specific type exposes it in a more-specific way -
Peter Huber almost 7 years@MarcGravell: Thanks for the information, although I don't really understand it in detail. For example I don't know if properties can be virtual and overridden. Methods are easier to understand. I came to this question, because my base class needed to call another virtual method in the base and not the overridden one. I got a stackoverflow, because the base class called the overriden version, which called the base class again. By changing override to new everything works fine now. I wish there would be a way to specify that the base virtual method needs to be called, but it seems impossible.
-
kofifus over 5 yearscan be done without the GetMethod reflection overhead ?
-
Guillermo Prandi almost 4 yearsYour code does not use actual inheritance (override of virtual methods). It just creates a new function with the same name, which is not what was asked.