有没有办法指定范围
本文关键字:范围 有没有 | 更新日期: 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;
}
}
但这只是一个概念的证明:这是可怕的,完全打破了多态性。
我认为你写这篇文章没有正当理由。