6

次の形式をとる拡張メソッドを定義したとします。

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
     }
}

ここではBazFooクラスのパブリック拡張メソッドを公開しています (例は簡単です)。次の使用法があるとします。

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 との完全な互換性が望まれます。

4

2 に答える 2

9

拡張メソッドをどのように表示するかによって異なります。それらは通常の静的メソッドの上にある構文糖衣にすぎないことを考えると、静的メソッドのガイドラインに従う必要があると思います-thisパラメーターを含むすべての引数を確認してください。

これは、特に処理する拡張機能がある場合に特に当てはまります。nullほとんどの人にとって拡張機能の使用が好まれていないことは承知していますが、次のような方法が好きです。

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}

public static void DisposeIfNotNull(this IDisposable source)
{
    if (source != null)
        source.Dispose();
}

null明らかに、これらのメソッドが機能するためには、パラメーターが許可されている必要があります。

于 2013-05-10T14:02:15.707 に答える