关于 C# 虚拟和重写机制如何在内部工作的话题已经在程序员中讨论到死......但是在谷歌上半小时后,我找不到以下问题的答案(见下文):
使用简单的代码:
public class BaseClass { public virtual SayNo() { return "NO!!!"; } } public class SecondClass: BaseClass { public override SayNo() { return "No."; } } public class ThirdClass: SecondClass { public override SayNo() { return "No..."; } } class Program { static void Main() { ThirdClass thirdclass = new ThirdClass(); string a = thirdclass.SayNo(); // this would return "No..." // Question: // Is there a way, not using the "new" keyword and/or the "hide" // mechansim (i.e. not modifying the 3 classes above), can we somehow return // a string from the SecondClass or even the BaseClass only using the // variable "third"? // I know the lines below won't get me to "NO!!!" BaseClass bc = (BaseClass)thirdclass; string b = bc.SayNo(); // this gives me "No..." but how to I get to "NO!!!"? } }
我想我不能简单地使用最派生的实例(不修改 3 个类的方法签名)来获取基类或中间派生类的方法。但我想确认并巩固我的理解......
谢谢。
最佳答案
C# 无法做到这一点,但在 IL 中使用 call
而不是 callvirt
实际上可以。因此,您可以使用 Reflection.Emit
解决 C# 的限制。结合 DynamicMethod
.
这里有一个非常简单的例子来说明它是如何工作的。如果您真的打算使用它,请将它包装在一个不错的函数中,努力使其适用于不同的委托(delegate)类型。
delegate string SayNoDelegate(BaseClass instance);
static void Main() {
BaseClass target = new SecondClass();
var method_args = new Type[] { typeof(BaseClass) };
var pull = new DynamicMethod("pull", typeof(string), method_args);
var method = typeof(BaseClass).GetMethod("SayNo", new Type[] {});
var ilgen = pull.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.EmitCall(OpCodes.Call, method, null);
ilgen.Emit(OpCodes.Ret);
var call = (SayNoDelegate)pull.CreateDelegate(typeof(SayNoDelegate));
Console.WriteLine("callvirt, in C#: {0}", target.SayNo());
Console.WriteLine("call, in IL: {0}", call(target));
}
打印:
callvirt, in C#: No.
call, in IL: NO!!!
关于c# - C# Virtual 和 Override 的内部工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/751849/