2014-07-09 20 views
5

Hãy xem xét các lớp và phương pháp sau đây:Null ngoại lệ nào để ném?

public class MyDto 
{ 
    public MyDtoChild Child {get; set;} 
} 

public void ProcessDto(MyDto myDto) 
{ 
    if(myDto == null) throw new ArgumentNullException("myDto"); 
    this.CheckSomething(myDto.Child.ChildProperty); 
} 

Nếu gọi với một MyDto với một null Child trái với các thiết bị riêng của nó này sẽ ném một NullReferenceException mà có thể là vô cùng khó khăn để chẩn đoán trong các phương thức phức tạp hơn.

Thông thường tôi ném một số ArgumentNullException vào lúc bắt đầu của phương thức nếu myDto là null nhưng ngoại lệ thích hợp để ném nếu myDto.Children là gì? An ArgumentNullException? A NullReferenceException? Ngoại lệ tùy chỉnh?

+0

Bạn có thể đảm bảo rằng 'MyDto.Child' sẽ không bao giờ rỗng bằng cách sử dụng công cụ sửa đổi' readonly' trên trường sao lưu của nó, giả sử rằng 'MyDto' sẽ sở hữu giá trị của trường. – Dai

+0

@KamilT đơn giản chỉ vì nó chỉ đưa tôi vài giờ để theo dõi nơi ref cụ thể này là đến và tôi muốn làm cho nó mạnh mẽ hơn cho các nhà phát triển trong tương lai. – Liath

+0

Có thể cho phép trẻ em được 'null' trong các phần khác của hệ thống hoặc trường hợp ngoại lệ của nó không? –

Trả lời

5

Như đã đề cập bởi các câu trả lời trước, nó không phải là một ArgumentNullException kể từ khi lập luận myDTO không phải là NULL. Với tôi, điều đó có ý nghĩa hơn khi ném một số ArgumentException vì đối số được chuyển cho phương thức không đáp ứng được các yêu cầu (bạn mong đợi Trẻ em không được rỗng). Hơn nữa, tình hình của bạn phù hợp với mô tả của ArgumentException:

ArgumentException được ném khi một phương pháp được gọi và ít nhất một của đối số được truyền không đáp ứng các đặc điểm kỹ thuật tham số của được gọi là phương pháp.

+0

Nhờ tất cả những người đưa ra đề xuất. Tôi đang chọn điều này như là câu trả lời vì nó xác nhận nhận xét của @Silvermind về việc không tăng refs null và đưa ra một mức độ tốt của mô tả tại sao. – Liath

3

Con của đối số của bạn không phải là đối số của bạn, vì vậy ArgumentNullException không phù hợp ở đây. Tôi nghĩ cách tốt nhất là ném NullReferenceException bằng một thông điệp giải thích.

+3

Không tăng [loại ngoại lệ dành riêng] (http://msdn.microsoft.com/en-us/library/ms182338.aspx) chẳng hạn như 'NullReferenceException'. Sử dụng 'InvalidOperationException' với một thông báo thích hợp. – Silvermind

4

Chắc chắn không phải là ArgumentNullException. Nếu bạn có thể truy cập vào tài sản Trẻ em của myDto của bạn, điều này có nghĩa là myDto, là đối số , là không null. Do đó, không có ArgumentNullException là myDto chính nó là không null.

Khi bạn đề xuất bạn có thể ném một số NullReferenceException và thêm thông điệp của riêng bạn để bạn biết vị trí này đến từ đâu và giải thích nó một cách độc đáo. Điều này hoàn toàn logic vì tài liệu tham chiếu đến thuộc tính bạn muốn sử dụng là null.

Như @Silvermind đã đề cập, không nên sử dụng NullReferenceException. Thay vào đó, bạn có các tùy chọn khác như ArgumentException hoặc InvalidOperationException. Một tùy chọn khác là tạo loại ngoại lệ của riêng bạn có nguồn gốc từ lớp Exception.

Ví dụ:

public class ChildNullException: Exception 
{ 
    public ChildNullException() { } 

    public ChildNullException(string message) 
     : base(message) 
    { 
    } 

    public ChildNullException(string message, Exception inner) 
     : base(message, inner) 
    { 
    } 
} 
+2

Không tăng [loại ngoại lệ dành riêng] (http://msdn.microsoft.com/en-us/library/ms182338.aspx) chẳng hạn như 'NullReferenceException'. Sử dụng 'InvalidOperationException' với một thông báo thích hợp. – Silvermind

+1

@Silvermind cảm ơn vì đã đề cập, không biết điều này! :) Tôi đã cập nhật câu trả lời của tôi theo đúng. – Abbas

4

Nếu đối số là không null nhưng bằng cách nào đó không hợp lệ, bạn nên ném một ArgumentException:

if(myDto == null) throw new ArgumentNullException("myDto"); 
if(myDto.Child == null) throw new ArgumentException("Property Child must not be null.", "myDto"); 
+0

Tôi nghĩ đây là giải pháp tốt hơn. 'ArgumentNullException' mong đợi một tham số xác định tham số theo tên là null. 'ArgumentException' là tổng quát hơn trong đó bạn cung cấp cho nó một thông báo cần xác định vấn đề (với thuộc tính con), và cho phép bạn xác định tham số gốc mà nó liên quan đến. – BrettJ

2

Từ lời giải thích của bạn tôi thấy rằng đây là một lỗi chương trình logic, không phải vấn đề dữ liệu. Bạn có thể tải thực thể con trước khi gọi phương thức này, và mọi thứ hoạt động tốt, hoặc bạn không tải con và logic này không thể được thực thi. Vì vậy, nó không có ý nghĩa để ném một số ngoại lệ tùy chỉnh ở đây, bởi vì sau khi bạn sửa chữa vấn đề lần đầu tiên, vấn đề sẽ không xảy ra một lần nữa.Chỉ cần nhìn thấy dấu vết ngăn xếp của ngoại lệ, sửa logic chương trình và quên trường hợp này. Sử dụng trình xử lý ngoại lệ toàn cục cho điều đó.