Các khối Try / Catch lồng vào nhau có phải là một ý tưởng tồi?


81

Giả sử chúng ta có một cấu trúc như vậy:

Try
  ' Outer try code, that can fail with more generic conditions, 
  ' that I know less about and might not be able to handle

  Try
    ' Inner try code, that can fail with more specific conditions,
    ' that I probably know more about, and are likely to handle appropriately
  Catch innerEx as Exception
    ' Handle the inner exception
  End Try

Catch outerEx as Exception
  ' Handle outer exception
End Try

Tôi đã thấy một số ý kiến ​​rằng việc lồng Trycác khối như thế này không được khuyến khích, nhưng tôi không thể tìm thấy bất kỳ lý do cụ thể nào.

Đây có phải là mã xấu? Nếu vậy, tại sao?


2
Không chắc chắn đoạn trích thực sự chính xác đến mức nào. Nhưng không có vấn đề gì mà bạn thực sự biết khi bắt được Exception. Nó có thể là bất cứ thứ gì . Cân nhắc tận dụng mệnh đề Khi mà VB.NET hỗ trợ.
Hans Passant

Câu trả lời:


85

Có một số trường hợp nhất định mà chúng là một ý tưởng hay, ví dụ: một lần thử / bắt cho toàn bộ phương pháp và một lần khác bên trong một vòng lặp khi bạn muốn xử lý ngoại lệ và tiếp tục xử lý phần còn lại của tập hợp.

Thực sự, lý do duy nhất để làm điều đó là nếu bạn muốn bỏ qua phần đã sai và tiếp tục, thay vì mở ngăn xếp và làm mất ngữ cảnh. Mở nhiều tệp trong trình chỉnh sửa là một ví dụ.

Điều đó nói rằng, các ngoại lệ nên (như tên của nó) phải là ngoại lệ. Một chương trình nên xử lý chúng nhưng cố gắng tránh chúng như một phần của quy trình thực thi bình thường. Chúng đắt về mặt tính toán trong hầu hết các ngôn ngữ (Python là một ngoại lệ đáng chú ý).

Một kỹ thuật khác có thể hữu ích là bắt các loại ngoại lệ cụ thể ...

Try
    'Some code to read from a file

Catch ex as IOException
    'Handle file access issues (possibly silently depending on usage)
Catch ex as Exception
    ' Handle all other exceptions.
    ' If you've got a handler further up, just omit this Catch and let the 
    ' exception propagate
    Throw
End Try

Chúng tôi cũng sử dụng thử / bắt lồng nhau trong các quy trình xử lý lỗi của mình ...

    Try
        Dim Message = String.Format("...", )
        Try
            'Log to database
        Catch ex As Exception
            'Do nothing
        End Try

        Try
            'Log to file
        Catch ex As Exception
            'Do nothing
        End Try
    Catch ex As Exception
        'Give up and go home
    End Try

7
Đăng nhập vào một chuỗi nền là một nơi tôi sẽ sử dụng thử / bắt bên trong. Tôi không muốn phương thức kết thúc vì nó không thể ghi lại những gì nó đang làm.
gooch

@Gooch đúng, tôi cũng làm vậy, tôi sẽ thêm nó vào câu trả lời của mình.
Cơ bản

37

Tôi thực sự không nghĩ rằng có bất cứ điều gì sai về các khối Try/ Catchkhối lồng nhau , ngoại trừ việc chúng có thể khó điều hướng và có khả năng là một dấu hiệu cho thấy bạn có thể thực hiện một số cấu trúc lại ( ví dụ: bên trong Try/ Catchthành phương pháp của riêng nó).

Nhưng tôi muốn giải quyết bình luận này:

' Outer try code, that can fail with more generic conditions, 
' that I know less about and might not be able to handle

Nếu bạn không biết cách xử lý các trường hợp ngoại lệ trong một tình huống cụ thể, hãy tin tôi: đừng bắt chúng. Tốt hơn là để ứng dụng của bạn gặp sự cố (ý tôi là bạn biết đấy, ghi lại nó; chỉ cần đừng nuốt nó) còn hơn để bắt một thứ gì đó mà bạn không biết cách khôi phục và sau đó để ứng dụng của bạn tiếp tục vui vẻ trong tình trạng bị hỏng . Tốt nhất là từ thời điểm đó, hành vi sẽ không thể đoán trước được.


Điều đó đúng. Tại thời điểm bắt được ngoại lệ bên ngoài, tôi sẽ không muốn tiếp tục. Tôi đã suy nghĩ nhiều hơn về khả năng tắt máy / khởi động lại ứng dụng một cách duyên dáng, và không gây sốc cho người dùng một "tai nạn xấu xí"
Goro

10
@Goro: Trong trường hợp đó, tôi muốn đề xuất một cơ chế xử lý ngoại lệ trên toàn ứng dụng (ví dụ: nếu đây là WinForms, hãy xử lý Application.UnhandledExceptionsự kiện) thay vì mỗi phương thức Try/ Catchkhối.
Dan Tao
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.