#c# #cil #ilgenerator
#c# #cil #ilgenerator
Вопрос:
Я генерирую метод с помощью ilgenerator, и у меня проблема. IlGenerator.BeginCatchBlock()
принудительно завершает работу, и в этом случае это недоступная инструкция.
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace Stack
{
class Program
{
static void Main(string[] args)
{
var asmName = new AssemblyName("Test");
var domain = Thread.GetDomain();
var assembly = domain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
var module = assembly.DefineDynamicModule("MyModule", "Test.dll", true);
var type = module.DefineType("MyType");
var method = type.DefineMethod("MyMethod", MethodAttributes.Public);
var ilg = method.GetILGenerator();
ilg.BeginExceptionBlock();
ilg.ThrowException(typeof(Exception));
ilg.BeginCatchBlock(typeof(Exception));
ilg.Emit(OpCodes.Pop);
ilg.EndExceptionBlock();
ilg.Emit(OpCodes.Ret);
type.CreateType();
assembly.Save("test.dll");
}
}
}
На самом деле, вывод выглядит как
.method public instance void MyMethod () cil managed
{
.maxstack 1
.try
{
IL_0000: newobj instance void [mscorlib]System.Exception::.ctor()
IL_0005: throw
IL_0006: leave IL_0011
} // end .try
catch [mscorlib]System.Exception
{
IL_000b: pop
IL_000c: leave IL_0011
} // end handler
IL_0011: ret
}
Я ожидал, что у меня не будет leave IL_0011 в блоке .try. PEVerify не показывает ошибок.
Комментарии:
1. Просто из любопытства, почему это проблема? Я понимаю, что
IL_0006: leave IL_0011
это недоступно, но это кажется достаточно безобидным?2. Взгляните на ссылочный источник.
ILGenerator
Функции, которые связаны с обработкой ошибок, сами по себе выдают несколько кодов операций, и do ничего не может с этим поделать.3. Надежное обнаружение недоступного кода сводится к проблеме остановки. В этом случае любой приличный компилятор мог бы увидеть, что инструкция недоступна, но
Reflection.Emit
не является компилятором, и поэтому он просто всегда выдаетleave
в конце блока, не прилагая больше усилий и не предоставляя вам возможность опустить ее, потому что вы знаете лучше. По той же причине PEVerify не жалуется, потому что недоступный IL-код не является ошибкой, он просто избыточен. Вы обнаружите, что такого рода «неоптимальный» IL на самом деле распространен, потому что это проще, и предполагается, что JIT-компилятор восполнит недостаток.4. Вы рассказали историю: у вас проблема, вы написали какой-то код, он сделал то, чего вы не ожидали. Это совершенно хорошая история, но здесь нет вопроса, на который мы могли бы ответить. В чем ваш вопрос? Если ваш подразумеваемый вопрос «что мне с этим делать?», то мой совет таков: когда ваши ожидания противоречат, научитесь признавать, что ваши ожидания были неправильными, и корректируйте их, чтобы они соответствовали реальности. Если это не ваш вопрос, то на самом деле задайте вопрос .