メソッドはnull値で呼び出されますか、それともnull参照例外が発生しますか?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
この場合、「this」パラメーターをチェックしてnullを調べる必要はありませんか?
メソッドはnull値で呼び出されますか、それともnull参照例外が発生しますか?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
この場合、「this」パラメーターをチェックしてnullを調べる必要はありませんか?
回答:
これは正常に動作します(例外はありません)。拡張メソッドは仮想呼び出しを使用しない(つまり、「callvirt」ではなく「call」il命令を使用する)ため、拡張メソッドで自分で記述しない限り、nullチェックはありません。これは実際にはいくつかの場合に役立ちます。
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
public static void ThrowIfNull<T>(this T obj, string parameterName)
where T : class
{
if(obj == null) throw new ArgumentNullException(parameterName);
}
等
基本的に、静的呼び出しの呼び出しは非常にリテラルです-つまり
string s = ...
if(s.IsNullOrEmpty()) {...}
になる:
string s = ...
if(YourExtensionClass.IsNullOrEmpty(s)) {...}
nullチェックがないことは明らかです。
Marc Gravellからの正解への追加。
this引数がnullであることが明らかな場合、コンパイラから警告が表示される可能性があります。
default(string).MyExtension();
実行時には正常に機能しますが、警告が表示され"Expression will always cause a System.NullReferenceException, because the default value of string is null"
ます。
すでに発見したように、拡張メソッドは単に美化された静的メソッドであるためnull
、NullReferenceException
スローされずに参照が渡されて呼び出されます。ただし、呼び出し元にとってはインスタンスメソッドのように見えるため、それらもそのように動作する必要があります。次に、ほとんどの場合、this
パラメータを確認し、そうであれば例外をスローしますnull
。null
以下の例のように、メソッドが明示的に値を処理し、その名前が適切に値を示している場合は、これを行わなくてもかまいません。
public static class StringNullExtensions {
public static bool IsNullOrEmpty(this string s) {
return string.IsNullOrEmpty(s);
}
public static bool IsNullOrBlank(this string s) {
return s == null || s.Trim().Length == 0;
}
}
nullが拡張メソッドに渡されます。
メソッドがnullかどうかをチェックせずにオブジェクトにアクセスしようとすると、はい、例外がスローされます。
ここの男は「IsNull」と「IsNotNull」拡張メソッドを書いて、参照がnullを渡されたかどうかをチェックします。個人的には、これは異常であり、一日のうちに見られるべきではなかったと思いますが、完全に有効なC#です。
他の人が指摘したように、null参照で拡張メソッドを呼び出すと、this引数がnullになり、特別なことは何も起こりません。これにより、拡張メソッドを使用してガード句を作成するというアイデアが生まれます。
例としてこの記事を読むことができます:循環的複雑さを軽減する方法:ガード節短いバージョンはこれです:
public static class StringExtensions
{
public static void AssertNonEmpty(this string value, string paramName)
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException("Value must be a non-empty string.", paramName);
}
}
これは、null参照で呼び出すことができる文字列クラス拡張メソッドです。
((string)null).AssertNonEmpty("null");
ランタイムがnull参照で拡張メソッドを正常に呼び出すため、呼び出しは正常に機能します。次に、この拡張メソッドを使用して、面倒な構文なしでガード句を実装できます。
public IRegisteredUser RegisterUser(string userName, string referrerName)
{
userName.AssertNonEmpty("userName");
referrerName.AssertNonEmpty("referrerName");
...
}
extensionmethodは静的なので、このMyObjectに対して何もしなくても問題はないはずです。簡単なテストで確認してください:)
Cannot perform runtime binding on a null reference
。