Các câu trả lời khác là hoàn toàn chính xác, nhưng câu trả lời này cung cấp thêm một số điều bất lợi, tôi nghĩ vậy.
Xem xét ví dụ này:
using System;
static class Program {
static void Main() {
try {
ThrowTest();
} catch (Exception e) {
Console.WriteLine("Your stack trace:");
Console.WriteLine(e.StackTrace);
Console.WriteLine();
if (e.InnerException == null) {
Console.WriteLine("No inner exception.");
} else {
Console.WriteLine("Stack trace of your inner exception:");
Console.WriteLine(e.InnerException.StackTrace);
}
}
}
static void ThrowTest() {
decimal a = 1m;
decimal b = 0m;
try {
Mult(a, b); // line 34
Div(a, b); // line 35
Mult(b, a); // line 36
Div(b, a); // line 37
} catch (ArithmeticException arithExc) {
Console.WriteLine("Handling a {0}.", arithExc.GetType().Name);
// uncomment EITHER
//throw arithExc;
// OR
//throw;
// OR
//throw new Exception("We handled and wrapped your exception", arithExc);
}
}
static void Mult(decimal x, decimal y) {
decimal.Multiply(x, y);
}
static void Div(decimal x, decimal y) {
decimal.Divide(x, y);
}
}
Nếu bạn bỏ ghi chú throw arithExc;
dòng, đầu ra của bạn là:
Handling a DivideByZeroException.
Your stack trace:
at Program.ThrowTest() in c:\somepath\Program.cs:line 44
at Program.Main() in c:\somepath\Program.cs:line 9
No inner exception.
Chắc chắn, bạn đã mất thông tin về nơi xảy ra ngoại lệ đó. Nếu thay vào đó bạn sử dụng throw;
dòng, đây là những gì bạn nhận được:
Handling a DivideByZeroException.
Your stack trace:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
at Program.ThrowTest() in c:\somepath\Program.cs:line 46
at Program.Main() in c:\somepath\Program.cs:line 9
No inner exception.
Điều này tốt hơn rất nhiều, bởi vì bây giờ bạn thấy rằng đó là Program.Div
phương pháp gây ra vấn đề cho bạn. Nhưng vẫn khó để xem vấn đề này xuất phát từ dòng 35 hay dòng 37 trong try
khối.
Nếu bạn sử dụng phương án thứ ba, gói trong một ngoại lệ bên ngoài, bạn sẽ không mất thông tin:
Handling a DivideByZeroException.
Your stack trace:
at Program.ThrowTest() in c:\somepath\Program.cs:line 48
at Program.Main() in c:\somepath\Program.cs:line 9
Stack trace of your inner exception:
at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
at System.Decimal.Divide(Decimal d1, Decimal d2)
at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
at Program.ThrowTest() in c:\somepath\Program.cs:line 35
Đặc biệt bạn có thể thấy rằng đó là dòng 35 dẫn đến vấn đề. Tuy nhiên, điều này đòi hỏi mọi người tìm kiếm InnerException
và cảm thấy hơi gián tiếp khi sử dụng các ngoại lệ bên trong trong các trường hợp đơn giản.
Trong bài đăng trên blog này, họ bảo toàn số dòng (dòng của khối thử) bằng cách gọi (thông qua sự phản chiếu) internal
phương thức intance InternalPreserveStackTrace()
trên Exception
đối tượng. Nhưng thật không hay khi sử dụng sự phản chiếu như vậy (.NET Framework có thể thay đổi internal
thành viên của họ một ngày nào đó mà không cần cảnh báo).