4

オブジェクトがnullかどうかをチェックしてインスタンス化するのに役立つ次の拡張メソッドがあります。上の 2 つは問題なく動作しますが、あまり役に立ちません。

    public static bool IsNull<T>(this T t)
    {
        return ReferenceEquals(t, null);
    }

    public static T NewIfNull<T>(this T t, Func<T> createNew)
    {
        if (t.IsNull<T>())
        {
            return createNew();
        }

        return t;
    }

    public static void Ensure<T>(this T t, Func<T> createNew)
    {
        t = t.NewIfNull<T>(createNew);
    }

最終的に私は次のようなことをしたいと思います

IList<string> foo;
...
foo.Ensure<IList<string>>(() => new List<string>());

ただし、Ensure メソッドは目的の効果を達成しません。つまり、 nullfooの場合は のインスタンスに設定し、それ以外のList<string>場合は基本的にそれ自体に設定します。

これを達成するためにEnsureメソッドを微調整できることがわかっている場合は、助けていただければ幸いです。

ありがとう、トム

4

4 に答える 4

10

オブジェクト変数を区別する必要があります。オブジェクトが null になることはありません。変数の値は null になる可能性があります。オブジェクトに関する何かを変更しようとしているのではありません (これ機能します)。呼び出し元の変数の値を変更しようとしています。

ただし、引数はデフォルトで値渡しされます。つまり、拡張メソッドはパラメーター(メソッド内で宣言された変数) を変更しますが、これは呼び出し元の変数には影響しません。通常、参照渡しのセマンティクスを実現するためにパラメーターを に変更できますrefが、拡張メソッドにはrefまたはout最初のパラメーターを含めることはできません。

他の人が言ったように、null 合体演算子 (??)を使用する方が良いでしょう。この式では、次の点に注意してください。

foo = foo ?? new List<string>();

が nullでない限り、新しいリストは作成されません。fooの右側のオペランドは??、必要でない限り評価されません。

于 2012-06-10T08:53:37.627 に答える
3

では、 null 合体演算子を複製しようとしていますか?

foo = foo ?? new List<string>();
于 2012-06-10T08:51:21.997 に答える
1

Ensureローカル参照変数 ( t)を設定しているだけで、それを返していないため、メソッドは機能しません。Ensureが返された場合t、次のことができます。

var list2 = list1.Ensure<List<string>>();

ただし、 ?? を使用できるため、それは必要ありません。オペレーター:

var list2 = list1 ?? new List<string>();
于 2012-06-10T08:51:44.403 に答える
0

が(または) パラメータでない場合Ensure、パラメータに何か新しいものを割り当ててtも、呼び出し元に対して何も変更されないため、メソッドは何もしません。代わりに、言うtrefout

IList<string> foo;
...
foo = foo.NewIfNull(() => new List<string>());

おそらくうまくいくでしょうが、他の人が言っているように、これは最も美しい方法ではありません。

于 2012-06-10T10:41:55.850 に答える