2009-01-20 29 views
38

Bạn sẽ coi loại ngoại lệ tốt nhất nào để ném khi phương thức mở rộng được gọi trên một cá thể rỗng (trong đó phương thức mở rộng không cho phép nó)? Vì các phương thức mở rộng là gì, nhưng các phương thức tĩnh bạn có thể tranh luận rằng nó nên là ArgumentNullException, nhưng mặt khác chúng được sử dụng như các phương thức ví dụ để nó có thể tự nhiên hơn khi sử dụng NullReferenceException. Hãy lấy ví dụ sau:ArgumentNullException hoặc NullReferenceException từ phương pháp mở rộng?

public static string ToInvariantString(this IFormattable value, string format) 
{ 
    return value.ToString(format, CultureInfo.InvariantCulture); 
} 

Bằng cách này, NullReferenceException sẽ bị ném nếu tham số giá trị rỗng.

Ví dụ khác sẽ là:

public static string ToInvariantString(this IFormattable value, string format) 
{ 
    if (value == null) throw new ArgumentNullException("value"); 
    return value.ToString(format, CultureInfo.InvariantCulture); 
} 

EDIT: Trong một số các câu trả lời bạn đã chỉ ra rằng một phương pháp khuyến nông có thể được gọi như một phương pháp tĩnh và trong những trường hợp ngoại lệ tham chiếu null sẽ là sai, đó là một điểm tuyệt vời, và thực sự là một trong những mối quan tâm của tôi, không chắc chắn lý do tại sao tôi quên đề cập đến trong câu hỏi ở nơi đầu tiên.

Một người nào đó cũng chỉ ra rằng việc ném NullReferenceException là sai, và có, đúng vậy. Đó là lý do tại sao tôi không ném nó, tôi chỉ để cho nó xảy ra (để CLR ném nó) bằng cách không bảo vệ phương pháp. Tôi nghĩ rằng tôi ủng hộ ArgumentNullException (đó là những gì tôi đã sử dụng cho đến nay) nhưng tôi vẫn nghĩ rằng có ít nhất là phòng để tranh luận chống lại NullReferenceException vì nó có vẻ tự nhiên hơn ở hầu hết các nơi mà phương pháp sẽ được dùng.

Trả lời

34

Nói chung, ngoại lệ được bao gồm, bạn nên coi phương pháp mở rộng như thể đó là phương pháp tĩnh bình thường. Trong trường hợp này, bạn nên ném một ArgumentNullException.

Ném một NullReferenceException đây là một ý tưởng tồi cho một vài lý do

  • Một tham chiếu null không thực sự xảy ra để nhìn thấy một là phản trực giác
  • Ném một NullReferenceException và gây ra một NullReferenceException xảy ra tạo ra ngoại lệ discernably khác nhau (Một cách để thấy sự khác biệt là mã lỗi). Điều này đúng với nhiều ngoại lệ được CLR đưa ra.

Xem When can you catch a StackOverflowException (bài đăng tôi đã làm về chủ đề này).

  • Hoàn toàn hợp pháp để gọi phương thức tiện ích giống như phương pháp thông thường. Trong trường hợp đó tôi chắc chắn sẽ không ngoại trừ một NullReferenceException, nhưng thay vào đó là một ArgumentNullException.
+0

Ý kiến ​​tuyệt vời và như tôi đề cập trong chỉnh sửa của tôi về bài viết này là lý do tôi không rõ ràng ném NullReferenceException, tôi vẫn để CLR ném nó. –

+0

"Một tham chiếu null không thực sự xảy ra". Có nó đã làm; bạn đã thông qua một tham chiếu null và phương thức đã cố gắng dereference nó. – piedar

+0

@piedar phương pháp đã cố gắng dereference nó, không phải là thời gian chạy! –

1

Từ quan điểm của người dùng, phương thức trông và hoạt động như một phương pháp thể hiện, vì vậy nếu tôi là họ, tôi sẽ mong đợi thấy một NullReferenceException.

Điều đó nói rằng, tôi sẽ đề nghị ném một hoặc một cách rõ ràng khác vào mã, thay vì chỉ "xảy ra" để ném một như trong ví dụ đầu tiên của bạn.

+0

Vâng, tôi đã nghĩ đến việc ném NullReferenceException một cách rõ ràng, nhưng cảm giác của tôi là nó nên được dành riêng cho trình biên dịch thực sự, nhưng bạn có thể rất đúng. –

+2

Từ quan điểm của người dùng, một phương pháp mở rộng có thể được gọi là cả hai bằng cách mở rộng hoặc là một phương pháp tĩnh. – JaredPar

1

ArgumentNullException. Có không yêu cầu để gọi các phương thức tiện ích mở rộng như thể chúng là các phương pháp thể hiện. Bạn có thể gọi chúng như thể chúng là phương pháp bình thường. NullReferenceException sẽ hoàn toàn không chính xác trong trường hợp đó.

6

Vì phương pháp mở rộng có thể được sử dụng trong C# 2.0 và chúng có thể được gọi giống như phương thức tĩnh (bạn KHÔNG phải sử dụng chúng làm phương thức mở rộng), bạn nên sử dụng ArgumentNullException.

Chỉ vì chúng xem như các phương pháp trên loại không có nghĩa là chúng là hoặc luôn được gọi là một.

19

Ngoài tất cả các câu trả lời khác (tốt) Tôi nghĩ đáng xem Microsoft đang làm gì để đảm bảo tính nhất quán ... và các phương pháp mở rộng trong Liệt kê tất cả đều ném ArgumentNullException theo như tôi thấy.

+0

Ý tưởng tuyệt vời, tôi đã có bản thân mình, đã không làm điều đó, không chắc chắn lý do tại sao! ;-) –

+1

Đây là một kỹ thuật hữu ích mà tôi sử dụng bản thân mình rất thường xuyên. Tuy nhiên, người ta phải luôn nhớ rằng chỉ vì FCL sử dụng một phương pháp cụ thể để đạt được điều gì đó, điều đó không có nghĩa là phương pháp đó là tối ưu hoặc chính xác. Tôi khuyên bạn nên nghĩ đến các phương pháp FCL như những gợi ý về cách đạt được điều gì đó, nhưng công đức của một phương pháp nhất định phải được so sánh với các phương án thay thế trước khi đánh giá liệu nó có phải là lựa chọn tốt nhất hay không. –

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