C#虚拟和覆盖的内部工作 [英] Internal Workings of C# Virtual and Override

查看:86
本文介绍了C#虚拟和覆盖的内部工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何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 of callvirt. You can thus work around C#'s limitation by using Reflection.Emit in combination with a DynamicMethod.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆