cherishty
cherishty

Reputation: 403

How to call base method from derived class instance in C#?

I have C# code, base class A and derived class B:

public class A
{
    public virtual void print() {Console.WriteLine("a"); }
}
public class B:A
{
    public override void print() { Console.WriteLine("b"); }
}

static void Main(string[] args)
{
    A a= new B();
    //In c++ I can use .Base:: to call base method from derived class instance
    a.Base::print();
}

I can't modify these two classes and I don't know what can I do in C#, any suggestion?


Additionally, thanks to everyone joining into this discussion, and I would like to clarify why I need this behavior:

In .net framework, we have an interface IPostBackDataHandler to handle postback. and in there is a method

public bool LoadPostData( string postDataKey, NameValueCollection postCollection )

When I implement it and test, I find sometimes the given postback type of postCollection is NameValueCollection ,while other time it's HttpValueCollection (a derived class of NameValueCollection)

Then,if it is a type of HttpValueCollection, when I get item from it, eg. postCollection['ControlID'] and I input html in this control, HttpValueCollection.get_item() will always validate the input and view it as a defect. While NameValueCollection.get_item() won't

I don't want it operate validation automatically, at least I should decide whether it should be validated, should I?

Upvotes: 4

Views: 18130

Answers (9)

Sr Bruno
Sr Bruno

Reputation: 11

It's easy enough to get around this. In the base class:

  protected void MethodToExtend() {
       SomeOtherMethod();
    }


protected void SomeOtherMethod() {
  // do something
}

Then, in the child class:

 protected new void MethodToExtend() {
       SomeOtherMethod();
       // do more stuff
    }

Upvotes: 0

Ivan Mladenov
Ivan Mladenov

Reputation: 1847

You cannot call the base method when you override it in the inherited. You can make the method in B to be new instead of override, but you lose the implementation.

public class A
{
    public virtual void Print() { Console.WriteLine("a"); }
}

public class B: A
{
    public new void Print() { Console.WriteLine("b"); }
}

This way when you call

static void Main(string[] args)
{
    A a = new B();
    a.Print(); // prints "a"
}

Otherwise, you can call base.Print() in the overridden method.

public class A
{
    public virtual void Print() { Console.WriteLine("a"); }
}

public class B: A
{
    public override void Print() 
    {
        base.Print();
        Console.WriteLine("b"); 
    }
}

Upvotes: 0

cherishty
cherishty

Reputation: 403

Thanks to everyone! Finally I realize this behavior need using reflection and delegate, like nocodename showing, here I find a similar method.

A a = new B();
var ptr = typeof(A).GetMethod("Print", new[] { typeof(_inputParameter) }).MethodHandle.GetFunctionPointer();
var baseGetItem = (Func<String, String>)Activator.CreateInstance(typeof(Func<String, String>), a, ptr);
String postedValue = baseGetItem(_parameter);

Upvotes: 1

nocodename
nocodename

Reputation: 1264

There is no way to access base method from outside the derived class. You can either write a method in derived class that will call base method like this:

public class B : A
{
    public override void print() { Console.WriteLine("B"); }

    public void basePrint() { base.print(); }
}

Or you can user Reflection to get base method definition and invoke it but it's rather ugly. Here is how to create DynamicMethod that calls base print method:

// Get MethodInfo of the base method
var methodInfo = typeof(A).GetMethod("Print", BindingFlags.Instance | BindingFlags.Public);

// Create DynamicMethod based on the methodInfo
var dynamicMethod = new DynamicMethod("BasePrint", methodInfo.ReturnType, new[] { methodInfo.DeclaringType }, methodInfo.DeclaringType);
// Create ILGenerator for the dynamic method
var il = dynamicMethod.GetILGenerator();

// Emit argument with index 0 - DeclaringType
il.Emit(OpCodes.Ldarg_0);
// Emit method call
il.EmitCall(OpCodes.Call, methodInfo, null);
// Emit method return value
il.Emit(OpCodes.Ret);

// Invoke method with target...
var b = new B();
dynamicMethod.Invoke(null, new object[] {b});

// ... or create a delegate and invoke method without target
var action = dynamicMethod.CreateDelegate(typeof(Action)) as Action;
action.Invoke();

Note that it'll work only for parameterless method. If you want to call method with parameters you'll have to put their types into the array with the DeclaringType and later emit all of them. Also you'll have to create delegate of type Action<parameterTypes or Func<returnType, parameterTypes> if the method returns something.

Upvotes: 6

Sweeper
Sweeper

Reputation: 274358

You can only call your base class's methods from the derived class (B) by doing:

base.print();

I don't think there is a way to do what you want to do, because it kind of breaks the point of polymorphism.

However, you can hide the print method in A by doing this in B:

new public void print() { Console.WriteLine("b"); }

This way, this code:

A a= new B();
a.print();

will call the print in A.

Upvotes: 3

Unknown_Coder
Unknown_Coder

Reputation: 774

You can simply call base class method from derived class by using "base" keywork:

see example,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            B obj= new B();
            obj.print();
            Console.ReadKey();
        }
    }

    public class A
    {
        public virtual void print() { Console.WriteLine("a"); }
    }
    public class B : A
    {
        public override void print() 
        {
            base.print();
            Console.WriteLine("b"); 
        }
    }

}

hope you understand! Thank u

Upvotes: 0

Omri Attiya
Omri Attiya

Reputation: 4037

The whole idea of override is that you will not call the base class's function. If you want to call A.print - use A object, if you want to call B.print use B object, and if you want an object that can use some of that and some of that - create it separately or use functions with different names, that might solve your problem.

I'm not sure what you are trying to accomplish here, but maybe you would like to read about Visitor Pattern

Good Luck!

Upvotes: 0

Darjan Bogdan
Darjan Bogdan

Reputation: 3910

You can't call base print outside of a class B i.e. from Main method due to way how override works in c#. However if you want to have possibility to do that, you should consider to shadow print method in class B:

public class B:A
{
    public new void print() { Console.WriteLine("b"); }
}

With new keyword class shadows member from parent class, so your line of code will work:

A a= new B();
a.print(); //prints "a"

and

B b= new B();
b.print(); //prints "b"

Upvotes: 0

schroedingersKat
schroedingersKat

Reputation: 189

var obj = new B();
obj.Print(); // overriden method
(obj as A).Print(); // base method

Upvotes: -2

Related Questions