hen*_*000 9 c# virtual inheritance overriding
关于C#虚拟和覆盖机制如何在内部工作的主题已经在程序员中讨论过死亡......但是在google上半小时之后,我找不到以下问题的答案(见下文):
使用简单的代码:
Run Code Online (Sandbox Code Playgroud)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个类的方法签名)来获取基类或中间派生类的方法.但我想证实并巩固我的理解......
谢谢.
Kon*_*lph 14
C#不能做到这一点,但它是实际运用中可能的IL call代替callvirt.因此,您可以Reflection.Emit结合使用来解决C#的限制DynamicMethod.
这是一个非常简单的例子来说明它是如何工作的.如果你真的打算使用它,将它包装在一个很好的函数中,努力使它适用于不同的委托类型.
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));
}
Run Code Online (Sandbox Code Playgroud)
打印:
callvirt, in C#: No.
call, in IL: NO!!!
Run Code Online (Sandbox Code Playgroud)
如果不对样品进行修改并对折射进行折扣,那就没有办法了.虚拟系统的目的是强制调用派生的最大值,无论什么,CLR擅长其工作.
有几种方法可以解决这个问题.
选项1:您可以将以下方法添加到ThirdClass
public void SayNoBase() {
base.SayNo();
}
Run Code Online (Sandbox Code Playgroud)
这将强制调用SecondClass.SayNo
选项2:这里的主要问题是您想要非虚拟地调用虚拟方法.C#只提供了一种通过基本修饰符完成此操作的方法.这使得无法以非虚方式调用自己类中的方法.您可以通过将其分解为第二种方法和代理来解决此问题.
public overrides void SayNo() {
SayNoHelper();
}
public void SayNoHelper() {
Console.WriteLine("No");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3727 次 |
| 最近记录: |