C#虚拟和覆盖的内部工作 [英] Internal Workings of C# Virtual and Override
问题描述
如何C#虚拟和控机制的话题作品内部已经讨论过死刑的程序员之中......但对谷歌半小时后,我无法找到答案以下问题(见下文):
使用一个简单的代码:
公共类BaseClass的
{
公共虚拟SayNo(){返回NO !!!; }
}
公共类二等:BaseClass的
{
公众覆盖SayNo(){返回否; }
}
公共类三级栏目:二等
{
公众覆盖SayNo(){返回不......; }
}
类节目
{
静态无效的主要()
{
三级栏目三级栏目=新三级栏目();
字符串= thirdclass.SayNo(); //这将返回不......
//问题:
//有没有办法,不使用new关键字和/或隐藏
// mechansim(即不修改3个班以上),可我们却不知何故返回
//只使用
//变量第三从二等甚至BaseClass的字符串?
//我知道下面的行不会得到我NO!
BaseClass的BC =(BaseClass的)三级栏目;
字符串B = bc.SayNo(); //这给了我不......但如何我得到NO !!!?
}
}
块引用>
我想我不能得到的基类,或者干脆利用最派生的实例中间派生类的方法(而无需修改3类的方法签名)。但我想确认和巩固我的理解...
感谢。
解决方案C#不能做到这一点,但它的是的实际上有可能在IL使用而不是
callvirt <
通话/ code>。因此,您可以解决C#的限制,通过使用
Reflection.Emit的
结合一个DynamicMethod的
。
下面是一个非常简单的例子来说明如何工作的。如果你真的打算利用这一点,把它包装一个漂亮的函数内力争使之与不同的委托类型的工作。
委托串SayNoDelegate(BaseClass的实例);
静态无效的主要(){
BaseClass的目标=新二等();
变种method_args =新类型[] {typeof运算(BaseClass的)};
变种拉=新的DynamicMethod的(拉的typeof(串),method_args);
VAR方法= typeof运算(BaseClass的).GetMethod(SayNo,新类型[] {});
VAR伊尔根= pull.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.EmitCall(OpCodes.Call,方法,NULL);
ilgen.Emit(OpCodes.Ret);
VAR调用=(SayNoDelegate)pull.CreateDelegate(typeof运算(SayNoDelegate));
Console.WriteLine(callvirt,在C#中:{0},target.SayNo());
Console.WriteLine(调用,在IL:{0},请致电(目标));
}
打印:
callvirt,在C#号
号召,IL:NO!
The topic of how C# virtual and override mechanism works internally has been discussed to death amongst the programmers... but after half an hour on google, I cannot find an answer to the following question (see below):
Using a simple code:
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!!!"? } }
I think I can't get to the methods of base class or the intermediate derived class simply using the most derived instance (without modifying the method signatures of the 3 classes). But I would like to confirm and cement my understanding...
Thanks.
解决方案C# can't do this but it is actually possible in IL using
call
instead ofcallvirt
. You can thus work around C#'s limitation by usingReflection.Emit
in combination with aDynamicMethod
.Here's a very simple example to illustrate how this works. If you really intend to use this, wrap it inside a nice function strive to make it work with different delegate types.
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)); }
Prints:
callvirt, in C#: No. call, in IL: NO!!!
这篇关于C#虚拟和覆盖的内部工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!