Вопрос

В настоящее время я изменяю широко используемый класс для перемещения как большую часть дорогой инициализации от конструктора класса в ленивые инициализированные свойства. Ниже приведен пример (в 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.

Это было полезно?

Решение

Вы можете рассмотреть возможность толкания ленивых свойств в базовый класс, чтобы избежать прямого доступа к ведущей переменной. Не идеально, я знаю. Я всегда думал, что это что-то не хватало в C # IE непосредственную поддержку ленивых свойств.

Другие советы

Ну, мое рекомендуемое решение было бы сказать, чтобы ваш сотрудник использовать свойство, а не поле. Но вы можете имитировать его до некоторой степени, как это:

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

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

Теперь довольно трудно прикрутить.

@Cibacity posted (и впоследствии) удалил [и позже восстановленный: 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 напрямую, и нет необходимости рассказывать вашему коллеги, который использовать ... есть только один.

Не говоря уже, что это правильный способ сделать это или что это шаблон, который должен или не следует следовать, я просто указываю на преимущества того, что предложил @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(); }

Увы, я не думаю, что ни одно из них доступны в настоящее время решениями в любой форме ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top