8

現在、広く使用されているクラスを変更して、高価な初期化の多くをクラス コンストラクターから Lazy Initialized プロパティに移動しています。以下に例を示します (c# の場合):

前:

public class ClassA
{
    public readonly ClassB B;

    public void ClassA()
    {
        B = new ClassB();
    }
}

後:

public class ClassA
{
    private ClassB _b;

    public ClassB B
    {
        get
        {
            if (_b == null)
            {
                _b = new ClassB();
            }

            return _b;
        }
    }
}

私が変更しているクラスには、これらのプロパティがかなり多くあり、特定のコンテキストでは使用されないものもあります (したがって遅延)。ただし、それらが使用されると、繰り返し呼び出される可能性があります。

残念ながら、プロパティはクラス内でも使用されることがよくあります。これは、プライベート変数 (_b) が初期化されずにメソッドによって直接使用される可能性があることを意味します。

クラス内でパブリック プロパティ (B) のみを使用できるようにする方法はありますか?

これはプログラマーから再投稿されたものです (明らかに主観的ではありません): https://softwareengineering.stackexchange.com/questions/34270/best-methods-for-lazy-initialization-with-properties

4

3 に答える 3

16

私が推奨する解決策は、フィールドではなくプロパティを使用するように同僚に伝えることです。しかし、次のようにして、ある程度ばかげた証明をすることができます。

public class ClassA
{
    private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());

    public ClassB B
    {
        get
        {
            return _b.Value;
        }
    }
}

今、台無しにするのはかなり難しいです。

于 2011-01-06T15:59:42.603 に答える
6

バッキング変数への直接アクセスを避けるために、遅延プロパティを基本クラスにプッシュすることを検討できます。私が知っている理想的ではありません。私はいつも、これは C# に欠けているもの、つまり遅延プロパティの直接サポートだと思っていました。

于 2011-01-06T16:00:58.757 に答える
3

@chibacity は、抽象基本クラスを使用する代替オプションを投稿 (およびその後) 削除 [および後で元に戻す :P] しました。コードの分散という点では理想的ではないかもしれませんが、多くのコードの混乱を取り除き、よりクリーンで簡潔な ClassA を作成する優れたカプセル化を提供します。たとえば、これらの手法を組み合わせて両方の目標を達成することを検討できます。

public class ClassB { /* Class to be lazily instantiated */ }

public abstract class BaseA
{
    private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());
    public virtual ClassB B { get { return _b.Value; } }
}

public class ClassA : BaseA
{
    public override ClassB B { get { return base.B; } }
}

一見すると、これはより長い道のりのように見えますが、ClassA が作業対象のクラスであると考えると、これはすべての参照が同じプロパティを通過することを意味します。フィールドが混乱を招く可能性があるため、プロパティをバイパスして _b を直接参照する必要はなく、同僚にどちらを使用するかを伝える必要もありません... 1 つしかありません。

これがこれを行う正しい方法である、またはこれが従うべきまたは従うべきではないパターンであると言っているのではなく、@chibacity が提案したことの利点を指摘しているだけです。

B.Value を参照することなく、暗黙的に遅延ロードされたプロパティを使用できると便利です...たとえば:

[Lazy]
public ClassB B { get; }

またはパラメーターなしのコンストラクターのないオブジェクトの場合

[Lazy(() => new ClassB("Hello", "World"))]
public ClassB B { get; }

または、@chibacity がコメントで提案したように

public ClassB B { lazyget; }

また

public ClassB B { lazyget : new ClassB(); }

残念ながら、これらのいずれも現在利用可能なソリューションではないと思います...

于 2011-01-06T16:55:15.867 に答える