2009-01-20 49 views
38

如果在空實例上調用擴展方法時(擴展方法不允許),您會認爲什麼是最佳異常類型?由於擴展方法不過是靜態方法,所以您可能會認爲它應該是ArgumentNullException,但另一方面,它們會像實例方法一樣使用,因此使用NullReferenceException可能更自然。讓我們來看看下面的例子:從擴展方法的ArgumentNullException或NullReferenceException?

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

這樣,如果值參數爲null一個NullReferenceException將被拋出。

另一個例子是:

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

編輯: 在一些你已經指出,一個擴展方法可以這樣調用靜態方法的答案,並在這些情況下,一個空引用異常會是錯誤的,這是一個很好的觀點,實際上是我的一個擔憂,我不確定爲什麼我忘記在第一個問題中提到這個問題。

有人還指出,拋出一個NullReferenceException是錯誤的,是的,它是。這就是爲什麼我不扔掉它,我只是讓它發生(讓CLR扔掉它),而不是守護這個方法。

我認爲我贊成ArgumentNullException(這是我迄今爲止使用的),但我仍然認爲至少有空間爭論反對NullReferenceException,因爲在大多數方法將要使用的地方它似乎更自然使用。

回答

34

一般來說,包括異常,你應該把擴展方法看作是一個普通的靜態方法。在這種情況下,你應該拋出一個ArgumentNullException。

扔在這裏一個NullReferenceException是有幾個原因

  • 空引用實際上並沒有發生這樣看到一個是違反直覺的
  • 拋出一個NullReferenceException並導致一個NullReferenceException發生一個壞主意產生discernably不同的異常(查看差異的一種方法是錯誤代碼)。 CLR引發的許多例外情況都是如此。

請參閱When can you catch a StackOverflowException(關於此主題的文章)。

  • 完全合法地調用擴展方法,就像它是一個常規方法一樣。在那種情況下,我肯定不會除了NullReferenceException,而是一個ArgumentNullException。
+0

偉大的評論和我在我的帖子編輯中提到這是我沒有明確拋出NullReferenceException的原因,我仍然讓CLR拋出它。 – 2009-01-20 22:10:12

1

從用戶的角度來看,該方法看起來和行爲像一個實例方法,所以如果我是他們,我希望看到一個NullReferenceException。

也就是說,我建議在代碼中明確地拋出一個或另一個,而不是像第一個例子那樣只是「發生」拋出一個。

+0

是的,我曾經想過明確拋出NullReferenceException,但我的感覺是它應該保留給編譯器,但你可能是對的。 – 2009-01-20 22:02:57

+2

從用戶的角度來看,可以通過擴展或靜態方法來調用擴展方法。 – JaredPar 2009-01-20 22:07:47

1

ArgumentNullException。有要求調用擴展方法的要求,就好像它們是實例方法一樣。你可以稱它們爲正常方法。在這種情況下,NullReferenceException將完全不正確。

6

由於擴展方法可以在C#2.0中使用,並且它們可以像靜態方法一樣調用(您不必將它們用作擴展方法),所以應該使用ArgumentNullException。

僅僅因爲他們看起來類似的方法並不意味着他們是或總是被稱爲一個。

19

除了所有其他的答案(這是好的),我認爲這是值得期待的就是微軟確實爲統一起見...在可枚舉擴展的方法都會拋出ArgumentNullException據我可以看到。