2010-07-06 42 views
11

Tôi đang tạo ứng dụng web asp.net trong .net 3.5 và tôi muốn biết khi nào nên sử dụng và khi nào không sử dụng Try Catch Cuối cùng chặn? Đặc biệt, phần lớn các bản thử của tôi được bao bọc xung quanh việc thực hiện các procs được lưu trữ và điền vào các trường văn bản hoặc các khung nhìn lưới? Bạn có sử dụng Try Catch EVERYTIME khi bạn thực thi proc được lưu trữ và điền một điều khiển hiển thị dữ liệu không?Khi nào nên sử dụng và khi nào không sử dụng Try Catch Cuối cùng

khối mã của tôi thường trông giống như:

protected void AddNewRecord() 
    { 
     try 
     { 
      //execute stored proc 
      // populate grid view controls or textboxes 
     } 
     catch (Exception ex) 
     { 
      //display a messagebox to user that an error has occured 
      //return 
     } 
     finally 
     { } 
    } 
+0

cũng thấy điều này: http://stackoverflow.com/questions/505471/how-often-should-i-use-try-and-catch-in-c – 0x49D1

+0

Kiểm tra sách "CLR via C#", ấn bản thứ 3 , bởi J. Richter. Nó bao gồm các khái niệm xử lý ngoại lệ một cách chi tiết và chắc chắn là một tham chiếu tốt. – ileon

Trả lời

10

Câu trả lời là "nó phụ thuộc".

Bạn có thể muốn sử dụng try{...} catch {...} xung quanh mọi hoạt động nguyên tử để nếu có sự cố, bạn có thể quay lại trạng thái tốt cuối cùng (sử dụng giao dịch). Đây có thể là một hoặc nhiều thủ tục được lưu trữ - nó phụ thuộc vào ứng dụng của bạn.

Nếu bạn đang đặt ngoại lệ, hãy đảm bảo bạn rõ ràng trong trường hợp ngoại lệ bạn bắt được. Bạn không nên có catch (Exception ex) hoặc catch() - được gọi là xử lý ngoại lệ "bắt tất cả" - nhưng có các câu lệnh bắt cụ thể như catch (IndexOutOfRangeException ex) (ví dụ) thay thế.

Tuy nhiên, nếu bạn không thể xử lý ngoại lệ hoặc không có gì bạn có thể làm để dọn dẹp, thì bạn không nên bẫy nó.

+0

Bạn có ý nghĩa gì bởi hoạt động "nguyên tử"? – user279521

+2

http://en.wikipedia.org/wiki/Atomic_operation –

+3

@ user279521 - "nguyên tử" - giống như một nguyên tử ở chỗ nó không thể được chia thêm nữa. Nó có thể có một số bước nhưng mỗi bước không có ý nghĩa nếu được thực hiện trên chính nó. Ví dụ, nếu bạn sửa chữa một lỗi trong mã của bạn nhưng điều đó yêu cầu chỉnh sửa đối với một số lớp, việc kiểm tra tất cả các tệp được cho là nguyên tử như việc kiểm tra trong một tệp không có ý nghĩa gì. – ChrisF

0

Hầu hết thời gian bạn không nên bắt ngoại lệ. Một số nơi có ý nghĩa để nắm bắt ngoại lệ, ví dụ:

Khi bạn có thể khôi phục từ ngoại lệ cụ thể đó. Khi bạn cần đăng nhập hoặc báo cáo (ví dụ: cho người dùng) - thường ở cấp cao nhất trong mã của bạn. Khi người gọi mã của bạn không thể xử lý các ngoại lệ, vì vậy bạn cần phải chuyển đổi chúng thành một số định dạng lỗi khác.

Ngoài ra, câu lệnh chặn sử dụng có thể được sử dụng để thực sự gọi là Vứt bỏ trên các đối tượng IDisposable, loại bỏ nhu cầu thử ... cuối cùng.

+0

Điều gì sẽ xảy ra nếu tôi muốn hiển thị hộp thông báo cho người dùng "Đã xảy ra lỗi trong khi tải dữ liệu"? Làm thế nào tôi có thể đạt được điều đó mà không có khối try catch? – user279521

+0

Bạn cần một try-catch để bật lên hộp thư với ngoại lệ –

+0

Như tôi đã nói, bạn chỉ cần điều này ở cấp cao nhất của mã của bạn: "Khi bạn cần phải đăng nhập hoặc báo cáo nó (ví dụ, cho người dùng) - thường ở cấp cao nhất trong mã của bạn. " – Polyfun

4

Bạn chỉ nên sử dụng try catch, khi bạn định xử lý ngoại lệ trong khối catch. Những gì tôi có nghĩa là bằng cách xử lý là, đăng nhập lỗi, chọn một con đường khác nhau vì lỗi, vv Nếu bạn chỉ đơn thuần là ý định tái ném nó, không có điểm trong có cố gắng bắt.

+1

Nếu bạn muốn đăng nhập lỗi, không cần phải nắm bắt ngoại lệ tại thời điểm xảy ra lỗi - thay vào đó bạn có thể nắm bắt điểm xuất phát từ mã của bạn, nhật ký bất kỳ ngoại lệ nào xảy ra ở bất kỳ đâu trong mã của bạn. – Polyfun

+0

Bạn làm cho một điểm tốt, nhưng tôi nghĩ rằng nó phần lớn phụ thuộc vào kiến ​​trúc tổng thể của ứng dụng. Thực sự tôi đã chỉ cung cấp nó như là một ví dụ về khi nào có thể sử dụng một thử bắt. – kemiller2002

+0

Điều gì sẽ xảy ra nếu một bất biến của đối tượng dựa vào việc có tất cả mã trong một khối thực thi? Tôi sẽ nghĩ rằng trong trường hợp như vậy, mã nên được bảo vệ bởi một khối mà sẽ rõ ràng vô hiệu hóa đối tượng nếu một ngoại lệ xảy ra tại thời điểm khi bất biến của đối tượng có thể không giữ. Nếu ngoại lệ sẽ gây ra mã gọi để từ bỏ đối tượng bị hỏng, hành động từ bỏ đối tượng tham nhũng sẽ giải quyết vấn đề. Nếu mã gọi cố gắng sử dụng đối tượng bị hỏng, những nỗ lực đó sẽ gây ra ngoại lệ, do đó buộc phải mở rộng hơn nữa cho đến khi mọi thứ được giải quyết hoặc chúng chết hoàn toàn. – supercat

1

Như những người khác đã nói, điều đó phụ thuộc. Tôi có xu hướng sử dụng các khối try/catch/finally trong hai trường hợp:

  • Tôi cần xử lý Ngoại lệ theo cách nào đó khác ngoài việc chỉ đơn giản là ném lại.

  • Tôi cần dọn sạch một số tài nguyên trong khối finally.

Khác với hai tình huống đó, tôi để mã gọi xử lý bất kỳ Ngoại lệ nào có thể xảy ra.

+0

Như một phần, 'using' về cơ bản là một khối' try-finally' để dọn sạch tài nguyên (thông qua 'Dispose'). – Brian

+0

@Brian - Đúng, nhưng không phải mọi thứ cần được dọn dẹp luôn thực hiện IDisposable (hoặc Dispose). –

1

Bên cạnh đó với những gì người khác đã nói, hãy chắc chắn để tránh làm điều này:

try 
    { 
     throw new ApplicationException("Fake sql ex"); 
    } 
    //catch and do nothing. swallowing exceptions 
    catch(Exception){ }     
+2

Xử lý ngoại lệ cho Pokemon: Phải bắt tất cả! –

0

gì là Exception bạn đang mong đợi từ các proc lưu trữ?Cung cấp cho bạn không sử dụng pokemon exception handling và biết chính xác ứng dụng của bạn được mong đợi làm gì, bất kỳ thứ gì không phù hợp với Ngoại lệ cụ thể bạn muốn bắt sẽ bị đối tượng Application chặn lại.

Nói cách khác không sử dụng catch {} hoặc catch (Exception), nhưng xử lý ngoại lệ đặc biệt:

catch(SqlException e) 
{ 
    // Log stacktrace and show a friendly error to your user 
} 

Sự kiện Application.Error là nơi hành vi bất ngờ nên bị bắt và dễ dàng hơn để theo dõi hơn chỉ đơn giản là có một sự trở lại của khách hàng đối với bạn nói "các trường của tôi không hiển thị bất kỳ thứ gì".

+0

Không có ngoại lệ cụ thể được mong đợi, nhưng "chỉ để được an toàn", tôi đã được nói trong quá khứ rằng tất cả các cuộc gọi cơ sở dữ liệu nên được gói trong cố gắng nắm bắt khối. – user279521

+0

Nhưng bạn không cần phải bắt ngoại lệ. Bạn có thể vui vẻ nắm bắt tất cả các SqlExceptions hoặc bất cứ cơ sở dữ liệu nào bạn đang sử dụng.Nếu cái gì khác được ném bạn có thể sẽ muốn biết về nó thay vì nó chết lặng lẽ –

0

Sử dụng "try catch" trong vòng lặp trong cùng nên tiếp tục thực hiện khi có ngoại lệ cụ thể xảy ra. Lưu ý rằng nếu bạn có vòng lặp thực hiện 10.000 lần và ngoại lệ xảy ra trên ví dụ: sự lặp lại thứ mười mà sẽ không ảnh hưởng đến 9,990 khác nó có thể hữu ích để bắt ngoại lệ và để cho vòng lặp tiếp tục đi. Mặt khác, nếu ngoại lệ chỉ ra một lỗi cho thấy lần thứ 11, 12, 13, vv qua vòng lặp cũng sẽ thất bại, sẽ nhanh hơn nhiều để cho phép ngoại lệ loại bỏ vòng lặp hơn để tiếp tục thử lại một thao tác điều đó sẽ không hoạt động.

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