Следующая примерная программа - это попытка использовать код операции ldvirtftn
. Вы видите, что это имя указывает на то, что код операции используется при загрузке указателя виртуальной функции в стек. В примере кода я создаю тип с 2 статическими методами Ldftn
и Ldvirtftn
, оба этих метода возвращают открытый делегат Base.Method()
, первая функция Ldftn
использует код операции ldftn
и работает неожиданно, так как Base.Method
является виртуальным. Второй метод использует Ldvirtftn
и, по-видимому, создал недопустимую программу. Что я делаю не так? Какова цель этого кода операции, кроме путаницы?Когда и как я могу использовать код операции Ldvirtftn?
public class Base
{
public virtual void Method()
{
Console.WriteLine("Base");
}
}
public class Child : Base
{
public override void Method()
{
Console.WriteLine("Child");
}
}
class Program
{
static void Main(string[] args)
{
AssemblyBuilder ab =AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"),AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = ab.DefineDynamicModule("TestModule");
TypeBuilder tb = mb.DefineType("TestType");
MethodBuilder method = tb.DefineMethod("Ldftn",MethodAttributes.Public | MethodAttributes.Static, typeof(Action<Base>), Type.EmptyTypes);
var ilgen = method.GetILGenerator();
ilgen.Emit(OpCodes.Ldnull);
ilgen.Emit(OpCodes.Ldftn, typeof(Base).GetMethod("Method"));
ilgen.Emit(OpCodes.Newobj, typeof(Action<Base>).GetConstructors()[0]);
ilgen.Emit(OpCodes.Ret);
method = tb.DefineMethod("Ldvirtftn", MethodAttributes.Public | MethodAttributes.Static, typeof(Action<Base>), Type.EmptyTypes);
ilgen = method.GetILGenerator();
ilgen.Emit(OpCodes.Ldnull);
ilgen.Emit(OpCodes.Ldvirtftn, typeof(Base).GetMethod("Method"));
ilgen.Emit(OpCodes.Newobj, typeof(Action<Base>).GetConstructors()[0]);
ilgen.Emit(OpCodes.Ret);
var type = tb.CreateType();
var func = Delegate.CreateDelegate(typeof(Func<Action<Base>>),tb.GetMethod("Ldftn")) as Func<Action<Base>>;
var func2 = Delegate.CreateDelegate(typeof(Func<Action<Base>>), tb.GetMethod("Ldvirtftn")) as Func<Action<Base>>;
func()(new Child());
func2()(new Child());
}
}
Фактически виртуальная отправка была тем, чем я был. Я не знал, что virtftn работает только при передаче экземпляра, поэтому я должен отправить его: ld instance, dup, ldvirtftn Method, newobj delegate ctor? – 2010-12-16 13:50:33