Đầu tiên, một số thông tin cơ bản:Reflection.Emit.ILGenerator Xử lý ngoại lệ Lệnh "Leave"
Tôi đang làm trình biên dịch cho một dự án trường học. Nó đã được làm việc, và tôi đang nỗ lực hết sức để sửa lỗi và/hoặc tối ưu hóa nó. Gần đây tôi đã chạy vào một vấn đề với là tôi phát hiện ra rằng các đối tượng ILGenerator tạo thêm leave
hướng dẫn khi bạn gọi bất kỳ phương pháp thành viên sau đây:
BeginCatchBlock()
BeginExceptFilterBlock()
BeginFaultBlock()
BeginFinallyBlock()
EndExceptionBlock()
Vì vậy, bạn bắt đầu một tuyên bố thử với một cuộc gọi đến BeginExceptionBlock()
, thêm một vài mệnh đề bắt với BeginCatchBlock()
, có thể thêm mệnh đề cuối cùng với BeginFinallyBlock()
và sau đó kết thúc khu vực mã được bảo vệ bằng EndExceptionBlock()
.
Các phương pháp tôi liệt kê sẽ tự động tạo ra một phân nhánh lệnh leave
hướng dẫn đầu tiên sau câu lệnh thử. Tôi không muốn điều này, vì hai lý do. Một, bởi vì nó luôn tạo ra một hướng dẫn leave
chưa được tối ưu hóa, thay vì hướng dẫn leave.s
, ngay cả khi chỉ phân nhánh hai byte. Và hai, bởi vì bạn không thể kiểm soát nơi mà lệnh rời đi. Vì vậy, nếu bạn muốn chi nhánh đến một số vị trí khác trong mã của bạn, bạn phải thêm biến cục bộ do trình biên dịch tạo, đặt tùy thuộc vào nơi bạn muốn đi vào bên trong câu lệnh try, hãy tự động tạo ra EndExceptionBlock()
lệnh leave
và sau đó tạo câu lệnh chuyển đổi bên dưới khối thử. OR, bạn chỉ có thể phát ra một leave
hoặc leave.s
hướng dẫn cho mình, trước khi gọi một trong những phương pháp trước đây, dẫn đến một xấu xí và không thể truy cập thêm 5 byte, như vậy:
L_00ca: leave.s L_00e5
L_00cc: leave L_00d1
Cả hai tùy chọn là không thể chấp nhận đối với tôi. Có cách nào để ngăn chặn việc tạo tự động các hướng dẫn leave
hay bất kỳ cách nào khác để chỉ định các khu vực được bảo vệ thay vì sử dụng các phương pháp này (điều này cực kỳ khó chịu và thực tế không có giấy tờ)?
EDIT Lưu ý: trình biên dịch C# tự thực hiện việc này, vì vậy không phải là có lý do chính đáng để ép buộc chúng tôi. Ví dụ, nếu bạn có .NET 4.5 beta, tháo rời các mã sau và kiểm tra việc thực hiện: (khối ngoại lệ bổ sung trong nội bộ)
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;
}
Cảm ơn câu trả lời. Tôi để nó mở vì tôi đã không chắc chắn nếu các giải pháp tôi tìm thấy (MethodBuilder.SetMethodBody) thực sự sẽ làm việc cho tôi - nó không có một tài liệu mô tả rất. Cảm ơn một lần nữa! – aboveyou00