4

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?

2
  • maybe dup dup2 Commented May 5, 2017 at 6:28
  • Essentially, you want the compiler to emit call rather than callvirt. Unfortunately, there's no current means of asking for that directly in C#. Commented May 5, 2017 at 6:34

9 Answers 9

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

It's pity that I can't modify the class itself. I guess even Reflection can only achieve the override method class B? Can it?
Well it's possible. You could get methodInfo from base class and construct the DynamicMethod. Then, using ILGenerator you should probably be able to Invoke this method. I don't know the context, but maybe you could create another class (let's say C) that derives from A and then call base.print() inside it?
I've updated my answer with the explanation of how to generate and create dynamicMethod.
3

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.

4 Comments

in which namespace does Base exist?
there is no such thing in c#
@LeiYang don't use the capital B, it's not a class it's a keyword msdn.microsoft.com/en-us/library/hfw7t1ce.aspx
You are right, but I can't edit the class itself.. :(
1

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);

Comments

0

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"

Comments

0

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!

Comments

0

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

Comments

0

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"); 
    }
}

Comments

0

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
    }

Comments

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

4 Comments

Since the print method is virtual, I doubt that this works?!? See also this .NET Fiddle.
It doesn't. It probably won't even compile. But it does call the base method.
it calls the overridden method.
While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.