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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/438939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:25:45  来源:igfitidea点击:

Is there any way to call the parent version of an overridden method? (C# .NET)

c#.netinheritance

提问by Jader Dias

In the code below I tried in two ways to access the parent version of methodTwo, but the result was always 2. Is there any way to get the 1 result from a ChildClass instance without modifying these two classes?

在下面的代码中,我尝试了两种方法来访问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();
    }
}

UpdateChrisW posted this:

更新ChrisW 发布了这个:

From outside the class, I don't know any easy way; but, perhaps, I don't know what happens if you try reflection: use the Type.GetMethod method to find the MethodInfo associated with the method in the ParentClass, and then call MethodInfo.Invoke

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

That answer was deleted. I'm wondering if that hack could work, just for curiosity.

那个回答被删了。我想知道这个 hack 是否可行,只是出于好奇。

采纳答案by Marc Gravell

At the IL level, you could probably issue a callrather than a callvirt, and get the job done - but if we limit ourselves to C# ;-p (editdarn! the runtime stops you: VerificationException: "Operation could destabilize the runtime."; remove the virtualand it works fine; too clever by half...)

在 IL 级别,您可能会发出 acall而不是 acallvirt并完成工作 - 但如果我们将自己限制在 C# ;-p (编辑该死!运行时会阻止您VerificationException:“操作可能会破坏运行时的稳定性。”; 删除在virtual它工作正常;聪明过头了...)

Inside the ChildClasstype, you can use base.methodTwo()- however, this is not possible externally. Nor can you go down more than one level - there is no base.base.Foo()support.

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

However, if you disable polymorphism using method-hiding, you can get the answeryou want, but for bad reasons:

但是,如果您使用方法隐藏禁用多态性,您可以获得您想要的答案,但原因很糟糕:

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

Now you can get a different answer from the same object depending on whether the variable is defined as a ChildClassor a ParentClass.

现在,根据变量是定义为 aChildClass还是 a ,您可以从同一个对象中得到不同的答案ParentClass

回答by Craig Stuntz

Inside of ChildClass.methodTwo(), you can call base.methodTwo().

在里面ChildClass.methodTwo(),你可以调用base.methodTwo()

Outside of the class, calling ((ParentClass)a).methodTwo()willcall ChildClass.methodTwo. That's the whole reason why virtual methods exist.

在课外,调用((ParentClass)a).methodTwo()调用ChildClass.methodTwo。这就是虚拟方法存在的全部原因。

回答by Vince Panuccio

To my knowledge, once a method has been overridden then you can't call the parent method.

据我所知,一旦一个方法被覆盖,你就不能调用父方法。

回答by Julius A

I would think that it is not possible unless you make instance of the ParentClass directly. Thats the very essense of inheritance, polymorphism...

我认为除非您直接创建 ParentClass 的实例,否则这是不可能的。这就是继承、多态的本质...

回答by Keith Robertson

As Mark Gravell said, no, not externally. But here's another hack I have used. ChildClasscan expose methodTwo()from the ParentClassfor its own use or for external use. In your case:

正如 Mark Gravell 所说,不,不是外部的。但这是我使用的另一个黑客。ChildClass可以公开methodTwo()ParentClass供自己使用或外用。在你的情况下:

class ChildClass : ParentClass {
    override public int methodTwo() {
        return 2;
    }
    public int ParentClass_methodTwo() {
        return base.methodTwo();
    }
}

// Now instead of
Console.WriteLine("ParentClass methodTwo: " + ((ParentClass)a).methodTwo());
// use
Console.WriteLine("ParentClass methodTwo: " + a.ParentClass_methodTwo());

In my case, the child class introduced the concept of a Peer, and I needed its override of methodTwo()to invoke the base version on the peer. By overridding it, however, it hid it... Or did it? This technique came to the rescue.

在我的例子中,子类引入了 Peer 的概念,我需要它的覆盖methodTwo()来调用 Peer 上的基本版本。然而,通过覆盖它,它隐藏了它......或者是吗?这种技术来拯救。

class ChildClass : ParentClass {
    ChildClass peer;
    override public int methodTwo() {
        return peer.ParentClass_methodTwo();
    }
    private int ParentClass_methodTwo() {
        return base.methodTwo();
    }
}

回答by user3208955

I stumbled upon this looking for help and ended up with my own approach to calling ancestor versions of a method. This is more of a work-around which assumes you can edit the ancestor class:

我偶然发现了这个寻求帮助并最终用我自己的方法来调用方法的祖先版本。这更像是一种解决方法,假设您可以编辑祖先类:

Put the functionality in question in the ancestor class into a static method, with the necessary parameters. The method in that class can call it so it need not duplicate the functionality, and the child class can call to that functionality if desired via the static method. That way, it can be done even within a method and can cite which specific class it wants to invoke. Also, it can access farther back ancestors than mere parents, which is the limitation of use "base".

将祖先类中的相关功能放入静态方法中,并带有必要的参数。该类中的方法可以调用它,因此它不需要复制功能,如果需要,子类可以通过静态方法调用该功能。这样,它甚至可以在一个方法中完成,并且可以引用它想要调用的特定类。此外,它可以访问比单纯的父母更远的祖先,这是使用“基地”的限制。

回答by Michal

As mentioned above, something is bad with your class design if you need to call "base.base" in PRODUCTION code. But it is quite legitimate to use this technique if you are debugging or searching some workarrounds while using external libraries you cannot compile. It is unpleasant that C# does not provide this option directly. Still you may use Kenneth Xu solution with IL generator and Emit. It works.

如上所述,如果您需要在 PRODUCTION 代码中调用“base.base”,那么您的类设计就会出现问题。但是,如果您在使用无法编译的外部库进行调试或搜索某些变通方法时,使用此技术是非常合理的。令人不快的是,C# 没有直接提供这个选项。您仍然可以将 Kenneth Xu 解决方案与 IL 生成器和 Emit 一起使用。有用。

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

For reference and a complete sample see http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html

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

Thank you Kenneth Xu!

谢谢徐健!

回答by HammrerEngineer

public class Parent 
{
    public string Method()
    {
       return "parent";

    }
}

public class Child:Parent
{
    public string Method()
    {
       return "child";

    }
}

Above code successfully overrides parent method yet value of parent method still unchanged.

上面的代码成功覆盖了父方法,但父方法的值仍然不变。

You can return values from the Both Parent classand Child classusing code below -

您可以使用以下代码从Parent 类Child 类返回值-

Child child = new Child();
string result = (((Parent)child).Method()) + child.Method();

But Visual Studio will show you a warning in Compile Time.

但是 Visual Studio 会在编译时向您显示警告。