2009-09-22 50 views
8

Có sự khác biệt về hành vi giữa:ném ngoại lệ mới vs Catch khối

if (s == null) // s is a string 
{ 
throw new NullReferenceException(); 
} 

Và:

try 
{ 
    Console.Writeline(s); 
} 


catch (NullReferenceException Ex) 
{ // logic in here 
} 

Cả hai trường hợp ngoại lệ ném của đối tượng null, nếu s là null. Ví dụ đầu tiên là dễ đọc hơn vì nó cho thấy chính xác nơi xảy ra lỗi (bit ngoại lệ nằm ngay bên cạnh dòng sẽ gây ra ngoại lệ).

Tôi đã thấy kiểu mã hóa này rất nhiều trên các blog khác nhau bởi nhiều trình độ khác nhau, nhưng tại sao không chỉ thực hiện logic chính bằng cách kiểm tra nếu s không rỗng và do đó lưu ngoại lệ từ khi được nâng lên? Có một nhược điểm để tiếp cận này?

Cảm ơn

+1

+1 Câu hỏi hay –

Trả lời

18

Không, Console.WriteLine(null) sẽ không ném ngoại lệ. Nó sẽ không in ra gì cả. Bây giờ, giả sử bạn có ý nghĩa giống như:

Console.WriteLine(s.Length); 

thì có ý nghĩa ... và bạn nên sử dụng biểu mẫu đầu tiên. Trường hợp ngoại lệ sẽ xảy ra khi bạn không thể dự đoán trước thời gian với thông tin hiện tại của mình. Nếu bạn có thể dễ dàng làm việc ra rằng có gì đó sai, nó không có ý nghĩa để thử một hoạt động đó là ràng buộc để thất bại. Nó dẫn đến mã khó hiểu và hoạt động kém hơn.

Vì vậy, NullReferenceException, ArgumentNullException và các nội dung tương tự sẽ không bị phát hiện trừ khi chúng thuộc về nasty API which sometimes throws exceptions which you can handle, but which shouldn't really be being thrown in the first place. Đây là lý do tại sao trong Hợp đồng Mã, hành vi mặc định cho hợp đồng không thành công là ném một ngoại lệ mà bạn không thể nắm bắt rõ ràng, ngoài việc bắt giữ mọi thứ (thường ở đâu đó ở đầu ngăn xếp).

+0

Cảm ơn bạn. Tôi có nghĩa là bất kỳ trường hợp mà biến được sử dụng (trong một phương pháp/ctor) nhưng gây ra một NullReferenceException hoặc tham chiếu đối tượng không được thiết lập để một thể hiện của một lỗi đối tượng. Một điều tôi đã được một người bạn cho biết là mã đầu tiên nên được sử dụng ở nơi ngoại lệ sẽ bị người gọi bắt? Vì vậy, nếu tôi có một phương thức khác gọi là biểu mẫu đầu tiên và có một khối catch cho dòng ngoại lệ được ném. Bạn có đồng ý với điều này không? – dotnetdev

+0

Điều gì, nếu có, là mối quan hệ giữa tham chiếu đối tượng không được đặt thành một thể hiện của một đối tượng và NRE? – dotnetdev

+0

Làm cách nào để biết liệu ngoại lệ có bị người gọi phát hiện không? Và sự khác biệt giữa một cách rõ ràng ném một ngoại lệ khi một cái gì đó sẽ đi sai (đó là nhiều thông tin hơn) và để cho các.NET framework ném một ngoại lệ chung NullRef? –

2

Như Jon Skeet đã đề cập, Console.WriteLine (null) sẽ không ném ngoại lệ.

Bên cạnh đó, tôi muốn nói rằng bạn nên 'thất bại nhanh'. Điều đó có nghĩa là bạn phải đặt các mệnh đề 'bảo vệ' trong các phương thức của mình và kiểm tra các đối số đã được đưa ra trong các phương thức của bạn nếu chúng có thể được coi là hợp lệ. Điều này cho phép bạn tự ném ngoại lệ và cung cấp thêm thông báo sẽ hữu ích khi gỡ lỗi. Thông điệp có thể đưa ra một dấu hiệu rõ ràng về những gì đã sai, và đó là nhiều handier sau đó nếu bạn đang phải đối mặt với một NullReferenceException đã được ném mà không có bất kỳ thông tin tốt trong tài sản tin nhắn của nó.

0

Nếu bạn đang dùng thiết kế theo cách tiếp cận kiểu hợp đồng cho mọi thứ thì một đoạn mã có thể chỉ định rằng nó ném ngoại lệ để xác định hợp đồng của nó và thực thi nó. Một nửa khác là, tất nhiên, gọi mã nhận ra hợp đồng và hoàn thành nó. Trong trường hợp này nó có nghĩa là nếu bạn biết một phương pháp sẽ ném một ngoại lệ nếu bạn vượt qua trong null (nghĩa là hợp đồng của nó là bạn không vượt qua null) thì bạn nên kiểm tra trước khi gọi nó.

Jon Skeet nói rằng phương pháp này sẽ không loại trừ ngoại lệ. Điều đó có thể hoặc có thể không đúng nhưng nguyên tắc bảo vệ cho các hợp đồng phương thức đứng (mà tôi tin là điểm của câu hỏi của bạn).

1

Nếu bạn đang viết thư viện lớp, có thể đôi khi bạn biết rằng nếu một tham số nhất định chứa giá trị null, điều đó có thể gây ra sự cố tiếp theo.Trong những trường hợp đó, tôi thường tìm cách ném một ngoại lệ (mặc dù tôi có thể sử dụng ArgumentNullException cho trường hợp đó) để người dùng thư viện lớp biết điều này sớm và rõ ràng nhất có thể.

Trường hợp ngoại lệ không phải lúc nào cũng là điều xấu.

1

Jon Skeet là đúng nhưng, nói chung, đó là tất cả câu hỏi về ngữ nghĩa.

Nếu tình huống có một số ý nghĩa ứng dụng (số, ngày sinh trong tương lai, v.v.) bạn có thể muốn kiểm tra trước khi thực hiện bất kỳ thao tác nào và ném ngoại lệ tùy chỉnh (nghĩa là ứng dụng).

Nếu tình hình thực sự là "ngoại lệ", chỉ cần viết mã như thể giá trị đã cho là chính xác. Xem, nếu bạn đặt thử nghiệm, bạn sẽ làm điều đó mọi lúc, biết rằng VM sẽ làm điều đó anyway trong trường hợp nó cần phải ném một ngoại lệ. Từ quan điểm hiệu năng, nếu lỗi xảy ra có sự xuất hiện nhỏ về mặt thống kê, nó không có ý nghĩa gì cả.

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