問題描述
我有這個(gè)代碼
try
{
//AN EXCEPTION IS GENERATED HERE!!!
}
catch
{
SqlService.RollbackTransaction();
throw;
}
上面的代碼在這段代碼中被調(diào)用
Code above is called in this code
try
{
//HERE IS CALLED THE METHOD THAT CONTAINS THE CODE ABOVE
}
catch (Exception ex)
{
HandleException(ex);
}
作為參數(shù)傳遞給方法HandleException"的異常包含堆棧跟蹤中throw"行的行號,而不是生成異常的實(shí)際行.有誰知道為什么會發(fā)生這種情況?
The exception passed as parameter to the method "HandleException" contains the line number of the "throw" line in the stack trace instead of the real line where the exception was generated. Anyone knows why this could be happening?
EDIT1好的,謝謝大家的回答.我把內(nèi)扣換成了
EDIT1 Ok, thanks to all for your answers. I changed the inner catch for
catch(Exception ex)
{
SqlService.RollbackTransaction();
throw new Exception("Enrollment error", ex);
}
現(xiàn)在我在堆棧跟蹤中有正確的行,但我必須創(chuàng)建一個(gè)新異常.我希望找到更好的解決方案:-(
Now I have the correct line on the stack trace, but I had to create a new exception. I was hoping to find a better solution :-(
EDIT2也許(如果你有 5 分鐘的時(shí)間)你可以嘗試這個(gè)場景來檢查你是否得到相同的結(jié)果,重新創(chuàng)建不是很復(fù)雜.
EDIT2 Maybe (if you have 5 minutes) you could try this scenario in order to check if you get the same result, not very complicated to recreate.
推薦答案
是的,這是異常處理邏輯的限制.如果一個(gè)方法包含多個(gè)拋出異常的 throw 語句,那么您將獲得最后一個(gè)拋出異常的行號.此示例代碼重現(xiàn)了此行為:
Yes, this is a limitation in the exception handling logic. If a method contains more than one throw statement that throws an exception then you'll get the line number of the last one that threw. This example code reproduces this behavior:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new Exception(); // Line 15
}
catch {
throw; // Line 18
}
}
}
輸出:
System.Exception: Exception of type 'System.Exception' was thrown.
at Program.Test() in ConsoleApplication1Program.cs:line 18
at Program.Main(String[] args) in ConsoleApplication1Program.cs:line 6
解決方法很簡單,只需使用輔助方法來運(yùn)行可能引發(fā)異常的代碼.
The work-around is simple, just use a helper method to run the code that might throw an exception.
像這樣:
static void Test() {
try {
Test2(); // Line 15
}
catch {
throw; // Line 18
}
}
static void Test2() {
throw new Exception(); // Line 22
}
這種尷尬行為的根本原因是 .NET 異常處理建立在操作系統(tǒng)對異常的支持之上.稱為 SEH,Windows 中的結(jié)構(gòu)化異常處理.這是基于堆棧幀的,每個(gè)堆棧幀只能有一個(gè)活動(dòng)異常..NET 方法有一個(gè)堆棧幀,與方法內(nèi)的范圍塊數(shù)量無關(guān).通過使用輔助方法,您可以自動(dòng)獲得另一個(gè)可以跟蹤其自身異常的堆棧幀.當(dāng)方法包含 throw 語句時(shí),抖動(dòng)還會自動(dòng)抑制內(nèi)聯(lián)優(yōu)化,因此無需顯式使用 [MethodImpl] 屬性.
The underlying reason for this awkward behavior is that .NET exception handling is built on top of the operating system support for exceptions. Called SEH, Structured Exception Handling in Windows. Which is stack-frame based, there can only be one active exception per stack frame. A .NET method has one stack frame, regardless of the number of scope blocks inside the method. By using the helper method, you automatically get another stack frame that can track its own exception. The jitter also automatically suppresses the inlining optimization when a method contains a throw statement so there is no need to explicitly use the [MethodImpl] attribute.
這篇關(guān)于堆棧跟蹤上的錯(cuò)誤行號的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!