Pergunta

Atualmente, estou alterando uma classe amplamente usada para mover o máximo da inicialização cara do construtor de classe em propriedades inicializadas preguiçosas. Abaixo está um exemplo (em C#):

Antes da:

public class ClassA
{
    public readonly ClassB B;

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

Depois:

public class ClassA
{
    private ClassB _b;

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

            return _b;
        }
    }
}

Existem mais algumas dessas propriedades na classe que estou alterando, e algumas não são usadas em certos contextos (daí a preguiça), mas se forem usados, é provável que sejam chamados repetidamente.

Infelizmente, as propriedades também são frequentemente usadas dentro da classe. Isso significa que existe um potencial para a variável privada (_b) ser usada diretamente por um método sem ser inicializado.

Existe uma maneira de disponibilizar apenas a propriedade pública (b) dentro da classe, ou mesmo um método alternativo com o mesmo inicializado quando necessário?

Isso é republicado de programadores (não subjetivos o suficiente aparentemente):https://softwareengineering.stackexchange.com/questions/34270/Best-Methods-for-lazy-inicialization-with-properties

Foi útil?

Solução

Você pode considerar empurrar as propriedades preguiçosas para uma classe base para evitar o acesso direto à variável de apoio. Não é o ideal, eu sei. Eu sempre pensei que isso era algo que faltava no suporte direto do C# IE para propriedades preguiçosas.

Outras dicas

Bem, minha solução recomendada seria dizer ao seu colega de trabalho para usar a propriedade, não o campo. Mas você pode à prova de idiota em algum grau assim:

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

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

Agora é muito difícil estragar tudo.

@Chibacity postado (e posteriormente) excluído [e posteriormente não selecionado: P] Uma opção alternativa usando uma classe base abstrata. Embora possa não ser ideal em termos de distribuição de código, ele fornece um bom encapsulamento, removendo muita confusão de código para uma classe mais limpa e mais sucinta. Por exemplo, você pode considerar combinar as técnicas para atingir os dois objetivos:

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

À primeira vista, parece que isso é mais longo, mas quando você considera a classe que é a classe em que você estaria trabalhando e agora significa que todas as suas referências estão passando pela mesma propriedade - não há desnecessário estranho Campo causando uma confusão potencial, não há como ignorar a propriedade para fazer referência diretamente _b e não há necessidade de dizer ao seu colega de trabalho que usar ... há apenas um.

Não estou dizendo que essa é a maneira certa de fazer isso ou que esse é um padrão que deve ou não ser seguido, estou apenas apontando as vantagens do que @Chibacity sugeriu que, de outra forma, poderia passar despercebido.

Seria bom se você pudesse ter propriedades implícitas de carregamento preguiçoso sem ter que se referir a B.Value ... por exemplo:

[Lazy]
public ClassB B { get; }

ou para objetos sem construtores sem parâmetros

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

ou talvez como @chibacity sugerido em um comentário

public ClassB B { lazyget; }

ou

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

Infelizmente, não acho que nenhuma dessas soluções atualmente esteja disponível de qualquer forma ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top