在下面的代码中,我尝试了两种方法来访问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(); } }
更新 ChrisW发布了这个:
从课外,我不知道任何简单的方法; 但是,也许,我不知道如果尝试反射会发生什么:使用Type.GetMethod方法查找与ParentClass中的方法关联的MethodInfo,然后调用MethodInfo.Invoke
那个答案被删除了.我想知道这个黑客是否可行,只是为了好奇.
在里面ChildClass.methodTwo()
,你可以打电话base.methodTwo()
.
在课堂之外,打电话((ParentClass)a).methodTwo()
会打电话ChildClass.methodTwo
.这就是存在虚拟方法的全部原因.
在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; } }
现在,您可以从同一对象获得不同的答案,具体取决于变量是定义为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 });
有关参考和完整示例,请参见 http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html
谢谢徐熙!!