首先,一些背景信息:
我正在为学校项目制作编译器。它已经在工作了,我正在花费大量的精力来修复错误和/或优化它。我最近遇到的一个问题是我发现 ILGenerator 对象生成了一个额外的leave
当您调用以下任何成员方法时的说明:
BeginCatchBlock()
BeginExceptFilterBlock()
BeginFaultBlock()
BeginFinallyBlock()
EndExceptionBlock()
因此,您可以通过调用来开始一个 try 语句BeginExceptionBlock()
,添加几个 catch 子句BeginCatchBlock()
,可能添加一个finally子句BeginFinallyBlock()
,然后结束受保护的代码区域EndExceptionBlock()
.
我列出的方法会自动生成leave
指令分支到 try 语句之后的第一条指令。我不想要这些,有两个原因。一,因为它总是生成未经优化的leave
指令,而不是leave.s
指令,即使它只分支两个字节。第二,因为你无法控制离开指令的去向。
因此,如果您想分支到代码中的其他位置,则必须添加编译器生成的局部变量,根据您想要在 try 语句中进入的位置进行设置,让EndExceptionBlock()
自动生成leave
指令,然后在 try 块下面生成一个 switch 语句。或者,你可以发出一个leave
or leave.s
在调用前面的方法之一之前,请自行指导,导致丑陋且无法访问的额外 5 个字节,如下所示:
L_00ca: leave.s L_00e5
L_00cc: leave L_00d1
这两种选择对我来说都是不可接受的。有什么办法可以阻止自动生成leave
指令,或者任何其他方式来指定受保护区域,而不是使用这些方法(这非常烦人并且实际上没有记录)?
编辑
注意:C# 编译器本身会执行此操作,因此似乎没有充分的理由将其强加给我们。例如,如果您有.NET 4.5 beta,请反汇编以下代码并检查其实现:(内部添加的异常块)
public static async Task<bool> TestAsync(int ms)
{
var local = ms / 1000;
Console.WriteLine("In async call, before await " + local.ToString() + "-second delay.");
await System.Threading.Tasks.Task.Delay(ms);
Console.WriteLine("In async call, after await " + local.ToString() + "-second delay.");
Console.WriteLine();
Console.WriteLine("Press any key to continue.");
Console.ReadKey(false);
return true;
}