有没有办法指定范围?

发布于 2025-01-07 14:54:46 字数 854 浏览 0 评论 0原文

考虑这个代码示例:

public abstract class Parent
{
    public int val;
    public Parent()
    {
        val = 0;
    }
    public virtual void foo()
    {
        inc();
    }

    public virtual void inc()
    {
        val = val + 10;
    }
}

public class Child : Parent
{
    public override void foo()
    {
        base.foo();
    }

    public override void inc()
    {
        val++;
    }
}

static void Main(string[] args)
{
    Parent p = new Child();
    Console.WriteLine("p.val = " + p.val);  //Output: p.val = 0
    p.foo();
    Console.WriteLine("P.val = " + p.val);  //Output: p.val = 1
}

我假设父类的 inc() 没有被调用,因为 {this} 指针实际上指向子对象,因此子对象的版本inc() 将从父对象的函数 foo() 中调用。有没有办法强制父函数 foo() 始终调用父函数 inc() 就像在 C++ 中使用 :: 运算符一样?

Consider this code sample:

public abstract class Parent
{
    public int val;
    public Parent()
    {
        val = 0;
    }
    public virtual void foo()
    {
        inc();
    }

    public virtual void inc()
    {
        val = val + 10;
    }
}

public class Child : Parent
{
    public override void foo()
    {
        base.foo();
    }

    public override void inc()
    {
        val++;
    }
}

static void Main(string[] args)
{
    Parent p = new Child();
    Console.WriteLine("p.val = " + p.val);  //Output: p.val = 0
    p.foo();
    Console.WriteLine("P.val = " + p.val);  //Output: p.val = 1
}

I am assuming the inc() of the Parent class did not get called because {this} pointer is actually pointing to a Child object so the Child's version of inc() will be called from the Parent object's function foo(). Is there a way to force the Parent's function foo() to always call parent's function inc() Like you could in C++ with :: operator?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

メ斷腸人バ 2025-01-14 14:54:46

不,非虚拟调用虚拟方法的唯一方法是使用 base.Foo。当然,您可以在 Parent 中编写一个非虚拟方法,并让 Parent.foo() 调用该方法以及默认方法Parent.inc() 的实现。

No, the only way you can call a virtual method non-virtually is with base.Foo. Of course, you could write a non-virtual method in Parent, and make Parent.foo() call that, as well as the default implementation of Parent.inc().

谎言 2025-01-14 14:54:46

你这个问题想太多了。

  • 如果您想要非虚拟调度,那么首先不要将方法设为虚拟

  • 如果您想要虚拟和非虚拟调度,那么创建两个方法,一个虚拟和一个静态

例如:

class Base
{
    protected static void NonVirtualFoo(Base b)
    {
        // Whatever
    }
    public virtual void Foo()
    {
        Base.NonVirtualFoo(this);
    }
}

class Derived : Base
{
    protected new static void NonVirtualFoo(Derived d)
    {
        // Whatever
    }
    public override void Foo()
    {
        Derived.NonVirtualFoo(this);
        Base.NonVirtualFoo(this);
    }
}

为工作使用正确的工具。如果您想要虚拟调度,则调用虚拟方法。如果您想要静态调度,则调用静态方法。不要试图对虚拟方法进行锤子攻击并使其静态分派;这违背了该工具的全部目的。

You're over-thinking the problem.

  • If you want non-virtual dispatch then don't make the methods virtual in the first place.

  • If you want both virtual and non-virtual dispatch then make two methods, one virtual and one static

For example:

class Base
{
    protected static void NonVirtualFoo(Base b)
    {
        // Whatever
    }
    public virtual void Foo()
    {
        Base.NonVirtualFoo(this);
    }
}

class Derived : Base
{
    protected new static void NonVirtualFoo(Derived d)
    {
        // Whatever
    }
    public override void Foo()
    {
        Derived.NonVirtualFoo(this);
        Base.NonVirtualFoo(this);
    }
}

Use the right tool for the job. If you want virtual dispatch then call a virtual method. If you want static dispatch then call a static method. Don't try to take a hammer to a virtual method and make it statically dispatched; that's working against the entire purpose of the tool.

嘿咻 2025-01-14 14:54:46

Child 实例将调用它自己的类型实现。

foo() 调用 base.foo()base.foo() 调用 inc(),其中本例 inc() 来自 Child,因为实例是 Child 类型,并且将使用此实现。

The Child instance will call its own type implementation.

foo() calls base.foo() and base.foo() calls inc(), which in this case inc() is from the Child, since the instance is Child type, and will use this implementation.

嗯,实际上是可能的正如这里所说的

这确实有效:

public abstract class Parent
{
    public int val;

    public Parent()
    {
        val = 0;
    }

    public virtual void foo()
    {
        MethodInfo method = typeof(Parent).GetMethod("inc");
        DynamicMethod dm = new DynamicMethod("BaseInc", null, new Type[] { typeof(Parent) }, typeof(Parent));
        ILGenerator gen = dm.GetILGenerator();
        gen.Emit(OpCodes.Ldarg_1);
        gen.Emit(OpCodes.Call, method);
        gen.Emit(OpCodes.Ret);

        var BaseInc = (Action<Parent>)dm.CreateDelegate(typeof(Action<Parent>));
        BaseInc(this);
    }

    public virtual void inc()
    {
        val = val + 10;
    }
}

但这只是一个概念证明< /em>:这可怕并且完全破坏了多态性

我认为你没有正当理由写这篇文章。

Well, it is actually possible as said here:

This does the trick:

public abstract class Parent
{
    public int val;

    public Parent()
    {
        val = 0;
    }

    public virtual void foo()
    {
        MethodInfo method = typeof(Parent).GetMethod("inc");
        DynamicMethod dm = new DynamicMethod("BaseInc", null, new Type[] { typeof(Parent) }, typeof(Parent));
        ILGenerator gen = dm.GetILGenerator();
        gen.Emit(OpCodes.Ldarg_1);
        gen.Emit(OpCodes.Call, method);
        gen.Emit(OpCodes.Ret);

        var BaseInc = (Action<Parent>)dm.CreateDelegate(typeof(Action<Parent>));
        BaseInc(this);
    }

    public virtual void inc()
    {
        val = val + 10;
    }
}

But it's only a proof of concept: it's horrible and totally breaks the polymorphism.

I don't think you can have a valid reason to write this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文