有没有办法指定范围

本文关键字:范围 有没有 | 更新日期: 2023-09-27 18:25:19

考虑以下代码示例:

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
}

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

有没有办法指定范围

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

你想得太多了。

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

  • 如果您同时想要虚拟和非虚拟调度,则制作两种方法,一种是虚拟的,一种为静态的

例如:

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

使用适合作业的工具。如果您想要虚拟调度,则调用一个虚拟方法。如果您想要静态调度,则调用一个静态方法。不要试图将锤子带到虚拟方法中,并使其静态调度;这违背了该工具的全部用途。

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

foo()调用base.foo()base.foo()调用inc(),在这种情况下,inc()来自Child,因为实例是Child类型,并且将使用此实现。

好吧,正如这里所说,这实际上是可能的:

这就成功了:

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

但这只是一个概念的证明:这是可怕的完全打破了多态性

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