2012-04-12 55 views
11

Trong mã của tôi, tôi đang gặp phải tình huống trong đó System.Reflection.TargetInvocationException bị ném. Trong một trường hợp cụ thể, tôi biết cách tôi muốn xử lý ngoại lệ gốc, nhưng tôi muốn ném tất cả các ngoại lệ khác. Tôi có thể nghĩ ra hai cách để làm điều này, nhưng tôi không chắc cái nào tốt hơn.Kiểm tra loại ngoại lệ bên trong

1.

try 
{ 
    //code 
} 
catch (System.Reflection.TargetInvocationException ex) 
{ 
    if (typeof(ex.InnerException) == typeof(SpecificException)) 
    { 
     //fix 
    } 
    else 
    { 
     throw ex.Innerexception; 
    } 
} 

2.

try 
{ 
    //code 
} 
catch (System.Reflection.TargetInvocationException ex) 
{ 
    try 
    { 
     throw ex.InnerException; 
    } 
    catch (SpecificException exSpecific) 
    { 
     //fix 
    } 
} 

Tôi biết rằng ném ngoại lệ nói chung là chậm, vì vậy tôi cảm thấy phương pháp đầu tiên có thể sẽ nhanh hơn. Ngoài ra, có cách nào tốt hơn để làm điều này mà tôi đã không nghĩ đến?

+2

2 là hấp dẫn, IMHO 1 là dễ đọc hơn và có lẽ tốt hơn từ một quan điểm thực hiện xem. – Gabber

+0

Câu hỏi: cuộc gọi đang ném 'TargetInvocationException' là gì? Đó là mã của bạn, hoặc bên thứ ba? –

+0

Mã được tạo ra đang đọc từ db. – geekchic

Trả lời

17

Mỗi giải pháp được đề xuất của bạn có vấn đề riêng.

Phương pháp đầu tiên kiểm tra loại ngoại lệ bên trong là chính xác là loại bạn mong đợi. Điều đó có nghĩa là một loại có nguồn gốc sẽ không khớp, có thể không phải là những gì bạn dự định.

Phương pháp thứ hai sẽ ghi đè dấu vết ngăn xếp của ngoại lệ bên trong với vị trí ngăn xếp hiện tại, như Dan Puzey đã đề cập. Phá hủy dấu vết ngăn xếp có thể phá hủy một dẫn bạn yêu cầu để sửa lỗi.

Các giải pháp về cơ bản là những gì DarkGray đăng, với đề nghị của Nick và với một gợi ý bổ sung của riêng tôi (trong else):

try 
{ 
    // Do something 
} 
catch (TargetInvocationException ex) 
{ 
    if (ex.InnerException is SpecificException) 
    { 
     // Handle SpecificException 
    } 
    else if (ex.InnerException is SomeOtherSpecificException) 
    { 
     // Handle SomeOtherSpecificException 
    } 
    else 
    { 
     throw; // Always rethrow exceptions you don't know how to handle. 
    } 
} 

Nếu bạn muốn tái ném một ngoại lệ mà hóa ra bạn có thể 't xử lý, không throw ex; vì điều đó sẽ ghi đè lên theo dõi ngăn xếp. Thay vào đó hãy sử dụng throw; để giữ lại dấu vết ngăn xếp. Về cơ bản nó có nghĩa là "Tôi thực sự không muốn nhập mệnh đề catch này, giả vờ tôi không bao giờ bắt được ngoại lệ".

Cập nhật: C# 6.0 cung cấp một cú pháp tốt hơn nhiều qua lọc Exception:

try 
{ 
    // Do something 
} 
catch (TargetInvocationException ex) when (ex.InnerException is SpecificException) 
{ 
    // Handle SpecificException 
} 
catch (TargetInvocationException ex) when (ex.InnerException is SomeOtherSpecificException) 
{ 
    // Handle SomeOtherSpecificException 
} 
+0

+1 để chỉ ra sự khác biệt giữa 'ném' và 'ném cũ;' – geekchic

-2
try 
{ 
    //code 
} 
catch (System.Reflection.TargetInvocationException ex) 
{ 
    if (ex.InnerException is SpecificException) 
    { 
     //fix 
    } 
    else 
    { 
     throw ex.InnerException; 
    } 
} 

hoặc

try 
{ 
    //code 
} 
catch (System.Reflection.TargetInvocationException ex) 
{ 
    SpecificException spExc = ex.InnerException as SpecificException; 
    if (spExc != null) 
    { 
     bla-bla spExc 
    } 
    else 
    { 
     throw ex.InnerException; 
    } 
} 

hoặc

try 
{ 
    //code 
} 
catch (System.Reflection.TargetInvocationException ex) 
{ 
    if (ex.InnerException.GetType() == typeof(SpecificException)) 
    { 
     //fix 
    } 
    else 
    { 
     throw ex.InnerException; 
    } 
} 
+0

Tại sao không sử dụng từ khoá 'is'? – Nick

+0

Mã của bạn không có chức năng khác với đề xuất ban đầu ban đầu và bạn cũng không cung cấp bất kỳ lý do hoặc biện minh nào cho mã. –

1

# của bạn 2 chắc chắn là một giải pháp thú vị!

Bạn cần phải cẩn thận mặc dù: TargetInvocationException thường sẽ được ném bởi một thành phần khác khi lần đầu tiên bị bắtInnerException. Nếu bạn throw ex.InnerException bạn sẽ hủy một số thông tin chứa trong đó (như dấu vết ngăn xếp) vì bạn đang ném lại từ một vị trí khác.

Vì vậy, trong số hai bạn đã đề xuất, tôi chắc chắn sẽ đề xuất với # 1. Tôi không biết về một sự thay thế trong cấu trúc mà bạn có. Tuy nhiên, InnerException sẽ bị ném đi ban đầu ở nơi khác - nó đáng để điều tra liệu có một nơi thanh lịch hơn để xử lý sự thất bại này hay không, gần với nơi mà ngoại lệ được ném ra.

Các vấn đề liên quan