如何在C#中从派生类实例调用基方法?

问题描述 投票:0回答:9

我有 C# 代码、基础

class A
和派生
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();
}

我无法修改这两个类,我不知道我可以在 C# 中做什么,有什么建议吗?


此外,感谢大家参与这次讨论,我想澄清一下为什么我需要这种行为:

在.net框架中,我们有一个接口IPostBackDataHandler来处理回发。其中有一个方法

public bool LoadPostData( string postDataKey, NameValueCollection postCollection )

当我实现它并测试时,我发现有时postCollection的给定回发类型是NameValueCollection,而其他时候它是HttpValueCollectionNameValueCollection的派生类)

然后,如果它是 HttpValueCollection 的类型,当我从中获取项目时,例如。 postCollection['ControlID'] 并且我在此控件中输入 htmlHttpValueCollection.get_item() 将始终验证输入并将其视为缺陷。而 NameValueCollection.get_item() 不会

我不希望它自动进行验证,至少应该决定是否应该验证它,不是吗?

c# inheritance
9个回答
6
投票

无法从派生类外部访问基方法。 您可以在派生类中编写一个方法来调用基方法,如下所示:

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

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

或者你可以使用

Reflection
来获取基本方法定义并调用它,但它相当丑陋。 以下是如何创建调用基本
DynamicMethod
方法的
print

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

请注意它仅适用于无参数方法。如果你想调用带有参数的方法,你必须使用

DeclaringType
将它们的类型放入数组中,然后发出所有它们。此外,如果方法返回某些内容,您还必须创建
Action<parameterTypes
Func<returnType, parameterTypes>
类型的委托。


3
投票

您只能通过以下方式从派生类 (

B
) 调用基类的方法:

base.print();

我认为没有办法做你想做的事情,因为它有点破坏了多态性的要点。

但是,您可以通过在 print 中执行此操作来

A
中隐藏
B
方法:

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

这样,这段代码:

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

会调用

print

中的
A


1
投票
谢谢大家! 最后我意识到这种行为需要使用反射和委托,就像

nocodename所示,在这里我找到了类似的方法。

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

0
投票
您不能在类

print

 之外调用基类 
B
,即从 
Main
 方法调用,因为 
override
 在 C# 中的工作方式。然而,如果你想有可能做到这一点,你应该考虑类 
B 中的 shadow
 print 方法:

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

使用父类中的

new

 关键字类 
shadows 成员,因此您的代码行将起作用:

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

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

0
投票
覆盖的整个想法是您不会调用基类的函数。 如果你想调用 A.print - 使用 A 对象,如果你想调用 B.print 使用 B 对象,如果你想要一个可以使用其中一些对象和其中一些对象的对象 - 单独创建它或使用不同的函数名称,这可能会解决您的问题。

我不确定你想在这里完成什么,但也许你想阅读有关

访问者模式

祝你好运!


0
投票
您可以使用“base”键简单地从派生类调用基类方法:

参见示例,

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

希望您理解!谢谢你


0
投票
在继承中重写基方法时,无法调用基方法。您可以将 B 中的方法设为

new

 而不是 
override
,但您会失去实现。

public class A { public virtual void Print() { Console.WriteLine("a"); } } public class B: A { public new void Print() { Console.WriteLine("b"); } }
打电话时请这样

static void Main(string[] args) { A a = new B(); a.Print(); // prints "a" }
否则,您可以在重写的方法中调用base.Print()。

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

0
投票
解决这个问题很容易。 在基类中:

protected void MethodToExtend() { SomeOtherMethod(); } protected void SomeOtherMethod() { // do something }
然后,在子班上:

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

-2
投票
var obj = new B(); obj.Print(); // overriden method (obj as A).Print(); // base method
    
© www.soinside.com 2019 - 2024. All rights reserved.