Vâng, tôi đào một chút về vấn đề này và đây là của tôi rất cá nhân kết luận:
Không bao giờ sử dụng “ném” ”nhưng luôn luôn thay đổi một ngoại lệ mới với nguyên nhân được chỉ định.
Đây là lập luận của tôi:
tôi bị ảnh hưởng bởi kinh nghiệm trước đây của tôi với Java và dự kiến C# ném là rất tương tự như của Java. Vâng, tôi đào thêm một chút về vấn đề này và đây là những quan sát của tôi:
static void Main(string[] args){
try {
try {
throw new Exception("test"); // 13
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
throw ex;// 17
}
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
}
Sản lượng:
System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 13
System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 17
trực giác, một lập trình viên Java lại có thể ngờ cả hai trường hợp ngoại lệ là như nhau:
System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 13
Nhưng tài liệu C# rõ ràng nói rằng đây là những gì được mong đợi:
Nếu một ngoại lệ được tái ném bằng cách xác định ngoại trừ trong báo cáo ném, stack trace được khởi động lại vào phương pháp hiện tại và danh sách các phương pháp gọi giữa các phương pháp ban đầu mà ném ngoại lệ và các phương pháp hiện hành sẽ bị mất.Để giữ thông tin theo dõi ngăn xếp ban đầu với ngoại lệ, hãy sử dụng câu lệnh ném mà không chỉ định ngoại lệ. ”
Bây giờ nếu tôi thay đổi một chút thử nghiệm (thay thế ném cũ; bằng cách ném; trên dòng 17).
try {
try {
throw new Exception("test"); // 13
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
throw;// 17
}
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Sản lượng:
System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 13
System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 17
Rõ ràng đây không phải là những gì tôi mong đợi (vì đây là câu hỏi ban đầu). Tôi bị mất điểm ném ban đầu trong dấu vết ngăn xếp thứ hai. Simon Whitehead liên kết lời giải thích, đó là việc ném; duy trì dấu vết ngăn xếp chỉ khi ngoại lệ không xảy ra trong phương pháp hiện tại. Vì vậy, "ném" mà không có tham số trong cùng một phương pháp là khá vô ích như, nói chung, nó sẽ không giúp bạn tìm ra nguyên nhân của ngoại lệ.
Làm những gì bất kỳ lập trình viên Java sẽ làm gì, tôi đã thay thế báo cáo kết quả trên dòng 17 theo:
throw new Exception("rethrow", ex);// 17
Sản lượng:
System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 13
System.Exception: rethrow ---> System.Exception: test
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 13
--- End of inner exception stack trace ---
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 17
mà là một kết quả tốt hơn nhiều.
Sau đó, tôi bắt đầu thử nghiệm với các cuộc gọi phương thức.
private static void throwIt() {
throw new Exception("Test"); // 10
}
private static void rethrow(){
try{
throwIt(); // 15
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
throw; // 18
}
}
static void Main(string[] args){
try{
rethrow(); // 24
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
}
Một lần nữa, dấu vết ngăn xếp không phải là những gì tôi (một lập trình Java) mong đợi. Trong Java, cả hai ngăn xếp sẽ giống nhau và có ba phương thức sâu dưới dạng:
java.lang.Exception: Test
at com.example.Test.throwIt(Test.java:10)
at com.example.Test.rethrow(Test.java:15)
at com.example.Test.main(Test.java:24)
Dấu vết ngăn xếp đầu tiên chỉ có hai phương thức sâu.
System.Exception: Test
at ConsoleApplication1.Program.throwIt() in Program.cs:line 10
at ConsoleApplication1.Program.rethrow() in Program.cs:line 15
Nó giống như là dấu vết ngăn xếp đã được phổ biến như một phần của quá trình giải phóng ngăn xếp. Nếu tôi đăng nhập theo dõi ngăn xếp để điều tra ngoại lệ tại thời điểm đó, có thể tôi đang thiếu thông tin quan trọng.
Dấu vết ngăn xếp thứ hai là ba phương pháp sâu nhưng dòng 18 (ném;) xuất hiện trong đó.
System.Exception: Test
at ConsoleApplication1.Program.throwIt() in Program.cs:line 10
at ConsoleApplication1.Program.rethrow() in Program.cs:line 18
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 24
Quan sát này tương tự như quan sát được thực hiện trước đó: dấu vết ngăn xếp không được giữ nguyên cho phạm vi phương pháp hiện tại và lần nữa tôi loại bỏ phương thức được gọi là ngoại lệ. Ví dụ, nếu rethow được viết như sau:
private static void rethrow(){
try{
if (test)
throwIt(); // 15
else
throwIt(); // 17
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
throw; // 20
}
}
sản lượng
System.Exception: Test
at ConsoleApplication1.Program.throwIt() in Program.cs:line 10
at ConsoleApplication1.Program.rethrow() in Program.cs:line 20
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 26
nào gọi đến throwIt() ném ngoại lệ? Stack nói dòng 20 là dòng 15 hay 17?
Giải pháp là giống như trước: quấn nguyên nhân trong một ngoại lệ mới trong đó sản lượng:
System.Exception: rethrow ---> System.Exception: Test
at ConsoleApplication1.Program.throwIt() in Program.cs:line 10
at ConsoleApplication1.Program.rethrow(Boolean test) in Program.cs:line 17
--- End of inner exception stack trace ---
at ConsoleApplication1.Program.rethrow(Boolean test) in Program.cs:line 20
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 26
kết luận đơn giản của tôi để tất cả điều này là không bao giờ sử dụng “ném;” nhưng luôn rethrow mới ngoại lệ với nguyên nhân được chỉ định.
yep, đọc lại tuyên bố.để giữ cho dấu vết ngăn xếp làm 'ném' không phải' ném ex2' –
Những người, hãy đọc mã thực tế. Trong một trường hợp, OP chỉ sử dụng 'throw' và trong trường hợp khác, chúng sử dụng' throw ex'. Tuy nhiên, trong tất cả * ba * trường hợp (nghĩa là, không chỉ trường hợp với 'ném ex'), có ba ngăn xếp khác nhau (được cho là). Nếu các dấu vết ngăn xếp thực sự khác nhau, thì đây thực sự là một câu hỏi thú vị. – siride
@mitch nếu bạn đọc câu hỏi, những gì tài liệu nói và những gì tôi quan sát là khác nhau! Đây là những gì tôi muốn làm rõ. Tại sao ex1 và ex2 ngăn xếp khác nhau nếu tôi nghĩ lại với "ném"? – cquezel