Is there any way to call the parent version of an overridden method? (C# .NET)
在下面的代码中,我尝试了两种方法来访问method2的父版本,但结果总是2。在不修改这两个类的情况下,是否有任何方法可以从ChildClass实例获得1结果?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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发布此:
From outside the class, I don't know
any easy way; but, perhaps, I don't
know what happens if you try
reflection: use the Type.GetMethod
method to find the MethodInfo
associated with the method in the
ParentClass, and then call
MethodInfo.Invoke
那个答案被删除了。我想知道那个黑客是否可以工作,只是出于好奇。
在
在班外,调用
在IL级别,您可能会发布一个
在
但是,如果使用方法隐藏禁用多态性,则可以得到所需的答案,但原因不好:
1 2 3 4 5 6 7 |
现在,根据变量是定义为
如前所述,如果需要在生产代码中调用"base.base",那么类设计就有问题。但是,如果您在使用无法编译的外部库的同时调试或搜索某些WorkarRounds,那么使用此技术是非常合法的。令人不快的是,C没有直接提供这个选项。不过,您可以将Kenneth Xu解决方案与IL生成器一起使用并发射。它起作用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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-grandrent-virtual-method.html
谢谢许肯尼斯!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Parent { public string Method() { return"parent"; } } public class Child:Parent { public string Method() { return"child"; } } |
上面的代码成功地重写了父方法,但父方法的值仍然保持不变。
可以使用下面的代码从父类和子类返回值-
1 2 |
But Visual Studio will show you a warning in Compile Time.
正如马克·格雷弗所说,不,不是外部的。但这是我用过的另一个黑客。
1 2 3 4 5 6 7 8 9 10 11 12 13 | class ChildClass : ParentClass { override public int methodTwo() { return 2; } public int ParentClass_methodTwo() { return base.methodTwo(); } } // Now instead of Console.WriteLine("ParentClass methodTwo:" + ((ParentClass)a).methodTwo()); // use Console.WriteLine("ParentClass methodTwo:" + a.ParentClass_methodTwo()); |
在我的例子中,子类引入了对等的概念,我需要它对
1 2 3 4 5 6 7 8 9 | class ChildClass : ParentClass { ChildClass peer; override public int methodTwo() { return peer.ParentClass_methodTwo(); } private int ParentClass_methodTwo() { return base.methodTwo(); } } |
据我所知,一旦方法被重写,就不能调用父方法。
我在寻找帮助的过程中偶然发现了这个问题,最终找到了自己调用方法的祖先版本的方法。这是一个假设您可以编辑祖先类的工作:
将祖先类中存在问题的功能放入带有必要参数的静态方法中。该类中的方法可以调用它,因此它不需要复制功能,并且如果需要,子类可以通过静态方法调用该功能。这样,即使在方法中也可以这样做,并且可以引用它想要调用的特定类。此外,它还可以访问比父母更远的祖先,这是使用"基地"的限制。
我认为除非您直接创建parentclass实例,否则是不可能的。这是遗传的本质,多态性…