سؤال

أقوم حاليًا بتغيير فئة مستخدمة على نطاق واسع لتحريك أكبر قدر من التهيئة باهظة الثمن من مُنشئ الفصل إلى خصائص تهيئة كسول. أدناه مثال (في 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) مباشرةً بطريقة دون تهيئة.

هل هناك طريقة لجعل الممتلكات العامة (ب) متوفرة فقط داخل الفصل ، أو حتى طريقة بديلة مع نفس التهيئة التي تمس الحاجة إليها؟

يتم إعادة نشر هذا من المبرمجين (وليس ذاتيًا بما يكفي على ما يبدو):https://softwareengineering.stackexchange.com/questions/34270/best-methods-for-lazy-initialization-with-properties

هل كانت مفيدة؟

المحلول

يمكنك التفكير في دفع الخصائص البطيئة إلى فئة أساسية لتجنب الوصول المباشر إلى متغير الدعم. ليست مثالية أعرف. لطالما اعتقدت أن هذا شيء يفتقر إلى الدعم المباشر للعقارات البطيئة.

نصائح أخرى

حسنًا ، سيكون الحل الموصى به هو إخبار زميلك في العمل باستخدام العقار ، وليس الحقل. لكن يمكنك أن تقاومها إلى حد ما إلى حد ما:

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

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

الآن من الصعب جدا أن تفسد.

تم حذف cibacity (وبعد ذلك) [وبعد ذلك undeleted: p] خيار بديل باستخدام فئة قاعدة مجردة. على الرغم من أنه قد لا يكون مثاليًا من حيث توزيع التعليمات البرمجية ، إلا أنه يوفر تغليفًا رائعًا لإزالة الكثير من فوضى التعليمات البرمجية لفئة أنظف وأكثر إيجازًا. على سبيل المثال ، يمكنك التفكير في الجمع بين التقنيات لتحقيق كلا الهدفين:

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

للوهلة الأولى ، يبدو أن هذا أمر طويل أكثر ، ولكن عندما تفكر في تلك الفئة التي ستعمل فيها ومع ذلك ، فإن هذا يعني الآن أن جميع مراجعك تمر بنفس العقار - لا يوجد غير ضروري غريب الحقل الذي يسبب ارتباكًا محتملًا ، لا يوجد ما يتجاوز العقار للإشارة إلى _b مباشرةً وليس هناك حاجة لإخبار زميلك في العمل ... هناك واحد فقط.

لا نقول أن هذه هي الطريقة الصحيحة للقيام بذلك أو أن هذا نمط يجب أو لا ينبغي اتباعه ، فأنا أشير فقط إلى مزايا ما اقترحه cibacity الذي قد لا يلاحظه أحد.

سيكون من الرائع أن يكون لديك خصائص محملة كسول ضمنية دون الحاجة إلى الرجوع إلى B.Value ... على سبيل المثال:

[Lazy]
public ClassB B { get; }

أو للكائنات التي لا تحتوي على مُنشئين بدون معلمات

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

أو ربما كما هو مقترح في التعليق

public ClassB B { lazyget; }

أو

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

للأسف ، لا أعتقد أن أيًا من هذه الحلول متوفرة حاليًا بأي شكل من الأشكال ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top