プロパティを持つ遅延初期化のための方法
-
26-09-2019 - |
質問
私は現在、怠惰な初期化プロパティにクラスのコンストラクタから高価な初期の限り移動するために広く使われているクラスを変更しています。下記(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-方法-怠惰な初期化-と、プロパティのの
解決
あなたはバッキング変数への直接アクセスを回避するために、基本クラスに怠惰な性質を押して考えることができます。理想的ではない私が知っています。私はいつも、これはC#で怠惰な性質のために、すなわち直接サポートを欠いたものだったと思ってきました。
他のヒント
さて、私の推奨されるソリューションは、プロパティではなく、フィールドを使用して、あなたの同僚に伝えることであろう。しかし、あなたは馬鹿プルーフ可能性があり、それをこのようなある程度ます:
public class ClassA
{
private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());
public ClassB B
{
get
{
return _b.Value;
}
}
}
今では台無しにすることはかなり難しいます。
@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に財産をバイパスし、使用する同僚を指示する必要はありませんありません。
は、これは、これを行うための正しい方法であるか、これが続くか、すべきではないはずですパターンであることを、私はちょうどそれがそうでなければ気付かないことが示唆され利点何@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(); }
ああ、私はこれらのいずれかが現在どのような形態で利用可能なソリューションとは思わない...