メソッドがnull値で呼び出されるか、またはnull参照例外が返されますか?C#では、nullオブジェクトの拡張メソッドを呼び出すとどうなりますか?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
これが当てはまる場合は、nullのために 'this'パラメータを確認する必要はありませんか?
メソッドがnull値で呼び出されるか、またはnull参照例外が返されますか?C#では、nullオブジェクトの拡張メソッドを呼び出すとどうなりますか?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
これが当てはまる場合は、nullのために 'this'パラメータを確認する必要はありませんか?
これは問題なく動作します。拡張メソッドは仮想呼び出しを使用しません(つまり、 "callvirt"ではなく "call" il命令を使用します)。したがって、拡張メソッドで自分で記述しない限り、ヌルチェックはありません。これは、いくつかのケースでは、実際に有用である:
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)) {...}
あり明らかにヌルチェックではありません。
+1、私の答えに追加のメモ。 –
Marc、 "仮想"コールについて話していますが、インスタンスメソッドでの非仮想コールでも同様です。私はここで "仮想"という言葉が間違っていると思います。 –
@Konrad:それは文脈によって異なります。 C#コンパイラは、通常、非仮想メソッドに対しても、正確にnullチェックを取得するためにcallvirtを使用します。 –
extensionmethodは静的なので、あなたはそれが問題になることはありませんMyObjectにこれに何もない場合は、簡単なテストでは、それを確認する必要があります:)
ヌルが拡張メソッドに渡されます。
このメソッドがnullをチェックせずにオブジェクトにアクセスしようとすると、例外がスローされます。
ここで男は "IsNull"と "IsNotNull"という拡張メソッドを書いています。個人的には、これは収差だと思うし、日光を見てはならないはずですが、それは完全に有効なC#です。
Marc Gravellから正解に追加されました。
この引数がnullであることは明らかである場合は、コンパイラから警告を受ける可能性は:
default(string).MyExtension();
はよく、実行時に機能しますが、警告"Expression will always cause a System.NullReferenceException, because the default value of string is null"
を生成します。
なぜ「常にSystem.NullReferenceExceptionを引き起こす」と警告するのでしょうか?実際、それは決してできませんか? – tpower
検証済み - 面白いコンパイラグリッチ;-p +1工夫のため –
@tpower:このチェックは、拡張メソッドを正しく処理するように更新されていないためです。私は実際に引数の型だけを必要とする拡張メソッドを呼び出そうとしたときにそれを見つけましたが、インスタンスはありませんでした。今私ははるかに長い静的メソッドを呼び出さなければなりません。 –
読解可能で縦向きにするには、いくつかのゴールデンルールがあります。
Bertrand Meyerのそんなスマートな男 – Trap
既に発見したように、拡張メソッドは単純に栄光の静的メソッドであるため、null
参照が渡され、NullReferenceException
がスローされることなく呼び出されます。しかし、呼び出し元にインスタンスメソッドのように見えるので、もと同様に動作する必要があります。ほとんどの場合、this
パラメータをチェックし、null
の場合は例外をスローする必要があります。私もいくつかの時間前にこのことについてa blog postを書いた
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
値の世話をし、その名前は以下の例のように、正式にそれを示している場合、これを行うにはないOKです。
他の人が指摘しているように、null参照で拡張メソッドを呼び出すと、この引数はnullになり、特別なことは起こりません。これにより、拡張メソッドを使用してガード句を記述するという考え方が生まれます。
あなたは例のために、この記事を読むことができる:
((string)null).AssertNonEmpty("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参照で呼び出すことができます文字列クラスの拡張メソッドです:How to Reduce Cyclomatic Complexity: Guard Clauseショートバージョンはこれですランタイムはヌル参照で拡張メソッドを正常に呼び出すためにのみ有効です。そして、あなたは厄介な構文なしガード条項を実施するために、この拡張メソッドを使用することができます。
public IRegisteredUser RegisterUser(string userName, string referrerName)
{
userName.AssertNonEmpty("userName");
referrerName.AssertNonEmpty("referrerName");
...
}
それはこれらの事を議論するために痛いことはありません。 – tpower
うれしいことはここにあります、時間を節約しました。 – famousgarkin
ご質問ありがとうございます。このサイトのコメントのいくつかは、議論することが決して痛いとtpowerが言っているように、あまりにも負になりつつあります。 – nixon