2010-10-27 5 views
17

Đây là một chút trừu tượng, nhưng có cách nào có thể để ném một ngoại lệ và có nó nhập nhiều khối catch? Ví dụ: nếu nó khớp với một ngoại lệ cụ thể, theo sau là một ngoại lệ không cụ thể.Tôi có thể thực thi nhiều khối Catch không?

catch(Arithmetic exception) 
{ 
    //do stuff 
} 
catch(Exception exception) 
{ 
    //do stuff 
} 

Trả lời

30

Hoàn toàn có thể chấp nhận có nhiều khối catch của các loại khác nhau. Tuy nhiên, hành vi là khối ứng cử viên đầu tiên xử lý ngoại lệ.

Nó sẽ không nhập BOTH khối catch. Khối catch đầu tiên phù hợp với loại ngoại lệ sẽ xử lý ngoại lệ cụ thể đó và không có ngoại lệ nào khác, ngay cả khi nó được xử lý lại trong trình xử lý. Bất kỳ cái nào tiếp theo sẽ bị bỏ qua khi một ngoại lệ đi vào một khối catch.

Để có một ngoại lệ bị bắt trong cả hai khối, bạn sẽ cần một trong hai khối tổ như vậy:

try 
{ 
    try 
    { 
     // Do something that throws ArithmeticException 
    } 
    catch(ArithmeticException arithException) 
    { 
     // This handles the thrown exception.... 

     throw; // Rethrow so the outer handler sees it too 
    } 
} 
catch (Exception e) 
{ 
    // This gets hit as well, now, since the "inner" block rethrew the exception 
} 

Ngoài ra, bạn có thể lọc trong xử lý ngoại lệ chung chung dựa trên loại cụ thể của ngoại lệ.

+2

Nesting hoạt động ok đối với các cấu trúc phân cấp đơn giản, một cấp nhưng có thể rất xấu nếu bạn đã chia sẻ mã cần chạy cho một số trường hợp ngoại lệ khác nhau. Đây không phải là một bất đồng với cách tiếp cận này, nhưng một quan sát rằng nó không phải lúc nào cũng thích hợp. – tvanfosson

+0

@tvanfosson: Vâng, đó là lý do tại sao tôi cũng đã thêm tùy chọn lọc. Tùy chọn của bạn cũng rất đẹp. –

18

Không. Không thể thực thi mã trong cả hai khối catch cho một ngoại lệ duy nhất.

Tôi có lẽ sẽ cấu trúc lại mã trong khối ngoại lệ chung thành thứ có thể được gọi từ một trong hai.

try 
{ 
    // blah blah blah 
{ 
catch(Arithmetic ae) 
{ 
    HandleArithmeticException(ae); 
    HandleGenericException(ae); 
} 
catch(Exception e) 
{ 
    HandleGenericException(e); 
} 
1

Bạn không thể có nhiều khối ngoại lệ xử lý cùng một ngoại lệ. Nhưng những gì bạn có thể làm là nắm bắt những ngoại lệ chung, sau đó cố gắng để cast cho cụ thể hơn, như thế này:

catch (Exception exception) 
{ 
    var aex = exception as ArithmeticException 
    if (aex != null) 
    { 
     // do stuff specific to this exception type 
    } 
    // then do general stuff 
} 
0

này được gọi là lọc ngoại lệ và không được hỗ trợ trong C# (Tôi đang nói nó có thể trong VB.NET).

Một công việc xung quanh sẽ là bắt ngoại lệ chung và sau đó kiểm tra loại ngoại lệ trong khối catch và thực hiện bất kỳ xử lý cụ thể nào trước khi tiếp tục với phần còn lại của khối.

1

Giống như những người khác cho biết ngoại lệ sẽ bị bắt bởi khối đánh bắt cụ thể nhất.

Điều này sẽ làm tôi thất vọng với xử lý ngoại lệ. Chúc các bạn có thể làm một cái gì đó giống như

catch (ArgumentNullExcpetion, ArugmentOutOfRangeException ex) 
{ 

} 

Thay vì phải làm

catch (ArgumentNullExcpetion e) 
{ 
} 
catch (ArugmentOutOfRangeException outOfRange) 
{ 
} 

Tôi hiểu lý do chống lại điều này mà bạn có thể làm những việc khác nhau cho trường hợp ngoại lệ khác nhau nhưng đôi khi tôi muốn kết hợp chúng.

+1

Không phải cả hai đều lấy được từ ArgumentException - nếu bạn thực sự muốn làm điều tương tự cho cả hai, chỉ cần bắt ArgumentException. Nếu bạn muốn bắt các ngoại lệ con, thì bạn cần phải lọc (và ném lại) ArgumentException bằng cách sử dụng logic điều kiện. Điểm chung của bạn là tốt, nhưng đây không phải là ví dụ tốt nhất. Có lẽ một cái gì đó như ValidationException (lỗi mô hình) và SqlException (ràng buộc vi phạm), nơi chúng không ở trong cùng một hệ thống phân cấp là một ví dụ tốt hơn. – tvanfosson

+1

Tôi không nghĩ rằng 100% của bạn ngay khi bạn nói "ngoại lệ sẽ bị bắt bởi khối catch cụ thể nhất" Điều đó cũng phụ thuộc vào thứ tự. Vì vậy, nếu bạn có một bắt tất cả mọi thứ đầu tiên sẽ luôn luôn rơi vào đó ngay cả khi bạn có những cái cụ thể hơn sau khi nó – jon

+0

tvanfosson. Nắm bắt tốt. Tôi chỉ làm ví dụ này lên trên bay. Bạn đúng, tôi có thể bắt được ngoại lệ chung của cha mẹ trong trường hợp này. Nhưng yeah tôi muốn một cách để bắt nhiều loại ngoại lệ không liên quan trong một khối catch –

2

Nếu bạn đang sử dụng VB.NET, bạn có thể trừu tượng trình xử lý lỗi trong ngoại lệ số học thành một hàm hoặc phương thức gọi luôn trả về false.

Sau đó, bạn có thể viết một cái gì đó như:

Catch ex as Arithmetic When HandleArithmetic() 
Catch ex as Exception 

End Try 

Không phải là tôi sẽ ủng hộ việc sử dụng như vậy, mặc dù tôi đã nhìn thấy nó khuyến khích cho các mục đích khai thác gỗ trước. Tôi không tin rằng có một C# tương đương.