鉴于以下代码,有没有办法可以调用A类方法X的版本?
class A
{
virtual void X() { Console.WriteLine("x"); }
}
class B : A
{
override void X() { Console.WriteLine("y"); }
}
class Program
{
static void Main()
{
A b = new B();
// Call A.X somehow, not B.X...
}
答案 0 :(得分:103)
使用C#语言结构,您无法从{em> outside 范围A
或B
显式调用基本函数。如果你真的需要这样做,那么你的设计就有一个缺陷 - 即该函数不应该是虚拟的,或者应该将基本函数的一部分提取到一个单独的非虚函数。
你可以从里面 B.X然后调用A.X
class B : A
{
override void X() {
base.X();
Console.WriteLine("y");
}
}
但那不是别的。
正如Sasha Truf在this answer中指出的那样,你可以通过IL来做到这一点。 你可以通过反思完成它,正如mhand在评论中指出的那样。
答案 1 :(得分:12)
您无法通过C#执行此操作,但您可以编辑MSIL。
主要方法的IL代码:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] class MsilEditing.A a)
L_0000: nop
L_0001: newobj instance void MsilEditing.B::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: callvirt instance void MsilEditing.A::X()
L_000d: nop
L_000e: ret
}
您应该将L_0008中的操作码从 callvirt 更改为调用
L_0008: call instance void MsilEditing.A::X()
答案 2 :(得分:9)
你不能,也不应该。这就是多态性的用途,因此每个对象都有自己的方式来做一些“基础”事情。
答案 3 :(得分:9)
你可以这样做,但不是你指定的那一点。在B
的上下文中,您可以通过调用A.X()
来调用base.X()
。
答案 4 :(得分:4)
我不知道它的历史问题。但对于其他googlers:你可以写这样的东西。但这需要改变基类,这使得外部库无法使用。
class A
{
void protoX() { Console.WriteLine("x"); }
virtual void X() { protoX(); }
}
class B : A
{
override void X() { Console.WriteLine("y"); }
}
class Program
{
static void Main()
{
A b = new B();
// Call A.X somehow, not B.X...
b.protoX();
}
答案 5 :(得分:2)
如果方法在派生类中声明为overrides
,则不可能。为此,派生类中的方法应声明为new
:
public class Base {
public virtual string X() {
return "Base";
}
}
public class Derived1 : Base
{
public new string X()
{
return "Derived 1";
}
}
public class Derived2 : Base
{
public override string X() {
return "Derived 2";
}
}
Derived1 a = new Derived1();
Base b = new Derived1();
Base c = new Derived2();
a.X(); // returns Derived 1
b.X(); // returns Base
c.X(); // returns Derived 2