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.这就是存在虚拟方法的全部原因.
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.
如上所述,如果您需要在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
谢谢徐熙!!