次の形式をとる拡張メソッドを定義したとします。
public class Foo
{
public void Bar(int arg) { ... }
}
public static class FooExtensions
{
public static void Baz(this Foo @this)
{
@this.Bar(0);// not null-proof
}
}
ここではBaz
、Foo
クラスのパブリック拡張メソッドを公開しています (例は簡単です)。次の使用法があるとします。
Foo foo1 = null;
foo1.Bar(0); // throws NullReferenceException
Foo foo2 = null;
foo2.Baz(); // again throws NullReferenceException
したがって、どちらの場合もコードは一貫して動作します。メンバー メソッドまたは拡張メソッドの呼び出しに関係なく、同じ NullReferenceException() がスローされます。これは、状況に何か問題があると感じさせます。私の考えは次のとおりです。
NullReferenceExceptions
ほとんどのガイドラインによると、許可するコードは貧弱です。拡張メソッドは、そのような悪い習慣の例です。ガイドラインに準拠し、パブリック API のように失敗しないコードを公開するには、次のような null 安全性チェックを行う必要があります。
public static void Baz(this Foo @this) { if (@this == null) { 新しい ArgumentNullException("@this") をスローします。 } @this.Bar(0); }
- どちらの場合も同じように動作するため、動作に一貫性があると、開発者は null 参照の状況を簡単に検出できます。つまり、拡張メソッドの呼び出しはコーダーにとって常に明らかであるとは限らないため、行
foo2.Baz()
が a をスローした場合、NullReferenceException
それは明らかfoo2
ですnull
。
上記の矛盾は、私にいくつかの結論を導きます。2 番目のポイントは、重要な懸念事項であるスタック トレースを見逃しています。標準的なNullPointerException
ケースでは、スタック トレースは直接行につながりますfoo1.Bar(0)
。拡張メソッドでは、例外がスローされる拡張メソッド内の行を指します。そのため、一貫した動作には一貫性のないスタック トレースが含まれます。
そして今、質問 - null 安全性に関して、「ベスト プラクティス」はサード パーティによって使用される予定の拡張メソッドにどのように適用されますか? パラメータに引数 null-proof 検証を@this
常に追加して、一貫性を無視する必要がありますか? それとも、グッド プラクティスのアドバイスを迂回する可能性のあるまれなケースですか?
編集
拡張機能を含むライブラリが公開される状況に対処しています。PostSharp やその他の同様の手法など、非組み込み/サード パーティのソリューションは使用しません。また、.NET 3.5 との完全な互換性が望まれます。