有没有办法调用重写方法的父版本?(C#.NET)

Jad*_*ias 37 .net c# inheritance

在下面的代码中,我尝试了两种方法来访问methodTwo的父版本,但结果总是2.有没有办法从ChildClass实例获得1结果而不修改这两个类?

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新 ChrisW发布了这个:

从课外,我不知道任何简单的方法; 但是,也许,我不知道如果尝试反射会发生什么:使用Type.GetMethod方法查找与ParentClass中的方法关联的MethodInfo,然后调用MethodInfo.Invoke

那个答案被删除了.我想知道这个黑客是否可行,只是为了好奇.

Cra*_*ntz 58

在里面ChildClass.methodTwo(),你可以打电话base.methodTwo().

在课堂之外,打电话((ParentClass)a).methodTwo() 打电话ChildClass.methodTwo.这就是存在虚拟方法的全部原因.

  • 迈克尔 - 你否决了某人对多态行为的解释?克雷格只是在解释为什么事情会这样运作,不要因为他们解释了一个你碰巧认为被过度使用的概念而对好的答案投反对票。 (4认同)
  • 我猜他是在开玩笑。:) (2认同)

Mar*_*ell 37

在IL级别,你可能会发出一个call而不是一个callvirt,并完成工作 - 但是如果我们将自己限制在C#;-p(编辑 darn!运行时会阻止你VerificationException:"操作可能会破坏运行时的稳定性.";删除在virtual它工作正常;太聪明了一半......)

ChildClass类型内部,您可以使用base.methodTwo()- 但是,这在外部是不可能的.你也不能超过一个级别 - 没有base.base.Foo()支持.

但是,如果使用方法隐藏禁用多态,则可以获得所需的答案,但原因很简单:

class ChildClass : ParentClass
{
    new public int methodTwo() // bad, do not do
    {
        return 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以从同一对象获得不同的答案,具体取决于变量是定义为a ChildClass还是a ParentClass.


Mic*_*hal 5

如上所述,如果您需要在PRODUCTION代码中调用“ base.base”,则对类设计不利。但是,如果在使用无法编译的外部库的同时进行调试或搜索某些工作环境,则使用此技术是完全合法的。C#不直接提供此选项是令人不快的。仍然可以将IL生成器和Emit一起使用Kenneth Xu解决方案。有用。

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 });
Run Code Online (Sandbox Code Playgroud)

有关参考和完整示例,请参见 http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html

谢谢徐熙!!