Propriedades do .NET - usar conjunto particular ou propriedade ReadOnly?

42

Em que situação devo usar um conjunto particular em uma propriedade versus torná-lo uma propriedade ReadOnly? Leve em consideração os dois exemplos muito simplistas abaixo.

Primeiro exemplo:

Public Class Person

    Private _name As String

    Public Property Name As String
        Get
            Return _name
        End Get
        Private Set(ByVal value As String)
            _name = value
        End Set
    End Property

    Public Sub WorkOnName()

        Dim txtInfo As TextInfo = _
            Threading.Thread.CurrentThread.CurrentCulture.TextInfo

        Me.Name = txtInfo.ToTitleCase(Me.Name)

    End Sub

End Class

// ----------

public class Person
{
    private string _name;
    public string Name
    {
        get { return _name; }
        private set { _name = value; }
    }

    public void WorkOnName()
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        this.Name = txtInfo.ToTitleCase(this.Name);
    }
}

Segundo exemplo:

Public Class AnotherPerson

    Private _name As String

    Public ReadOnly Property Name As String
        Get
            Return _name
        End Get
    End Property

    Public Sub WorkOnName()

        Dim txtInfo As TextInfo = _
            Threading.Thread.CurrentThread.CurrentCulture.TextInfo

        _name = txtInfo.ToTitleCase(_name)

    End Sub

End Class

// ---------------

public class AnotherPerson
{
    private string _name;
    public string Name
    {
        get { return _name; }
    }

    public void WorkOnName()
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        _name = txtInfo.ToTitleCase(_name);
    }
}

Ambos produzem os mesmos resultados. Esta é uma situação em que não há certo e errado, e é apenas uma questão de preferência?

    
por tgxiii 29.04.2011 / 18:55
fonte

7 respostas

38

Existem algumas razões para usar private set .

1) Se você não estiver usando um campo de apoio e quiser uma propriedade automática somente leitura:

public string Name { get; private set; }   

public void WorkOnName()
{
    TextInfo txtInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
    Name = txtInfo.ToTitleCase(Name);
}  

2) Se você quiser fazer um trabalho extra ao modificar a variável dentro de sua classe e quiser capturar isso em um único local:

private string _name = string.Empty;
public string Name 
{ 
    get { return _name; }
    private set 
    {
        TextInfo txtInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
        _name = txtInfo.ToTitleCase(value);
    }
}

Em geral, porém, é uma questão de preferência pessoal. Até onde sei, não há razões de desempenho para usar uma sobre a outra.

    
por 29.04.2011 / 19:16
fonte
26

Use o conjunto particular quando quiser que o conjunto não possa ser acessado de fora .

Use somente leitura quando quiser definir a propriedade somente uma vez . No construtor ou no inicializador de variáveis.

TESTE:

void Main()
{
    Configuration config = new Configuration();
    config.ResetConfiguration();

    ConfigurationReadOnly configRO = new ConfigurationReadOnly();
    configRO.ResetConfiguration();
}

public class Configuration
{
    public Color BackgroundColor { get; private set; }
    public Color ForegroundColor { get; private set; }
    public String Text { get; private set; }

    public Configuration()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }

    public void ResetConfiguration()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }
}

public class ConfigurationReadOnly
{
    public readonly Color BackgroundColor;
    public readonly Color ForegroundColor;
    public readonly String Text;

    public ConfigurationReadOnly()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }

    public void ResetConfiguration()
    {
        BackgroundColor = Color.Black; // compile error: due to readonly keyword
        ForegroundColor = Color.White; // compile error: due to readonly keyword
        Text = String.Empty; // compile error: due to readonly keyword
    }
}
    
por 05.03.2013 / 17:39
fonte
8

Posso sugerir uma terceira opção?

public class Person
{
    public string Name { get; protected set; }

    public void SetName(string name)
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        this.Name = txtInfo.ToTitleCase(name);
    }
}

Isso torna a propriedade Name efetivamente somente leitura para todos os códigos externos e fornece um método Set explícito. Eu prefiro o conjunto explícito em vez de simplesmente usar o set na propriedade Name porque você está alterando o valor ao configurá-lo. Normalmente, se você definir um valor de propriedade, espera receber o mesmo valor quando chamar o get mais tarde, o que não aconteceria se você fizesse seu ToTitleCase no < em> definir .

No entanto, como você disse, não há uma resposta certa.

    
por 29.04.2011 / 19:12
fonte
4

Não use o segundo exemplo. O ponto inteiro de usar uma propriedade - mesmo se não houver nada acontecendo além do getter e da configuração do setter - é afunilar todo o acesso através desse getter e setter para que, se você precisar mudar o comportamento no futuro, esteja tudo em ordem. um lugar.

Seu segundo exemplo abandona isso no caso de definir a propriedade. Se você usasse essa abordagem em uma classe grande e complexa, e mais tarde precisasse alterar o comportamento da propriedade, estaria em busca e substituição de terreno, em vez de fazer a mudança em um único lugar - o setter privado.

    
por 30.04.2011 / 00:23
fonte
4

A partir do C # 6.0, as propriedades automáticas somente de getter foram adicionadas ao idioma. Veja aqui: link .

Veja um exemplo:

public class SomeClass
{
    public int GetOnlyInt { get; }

    public int GetOnlyIntWithInitializer { get; } = 25;

    public SomeClass(int getOnlyInt)
    {
        GetOnlyInt = getOnlyInt;
    }
}
    
por 06.07.2016 / 23:16
fonte
2

Sempre que eu precisei alterar o nível de acesso de um setter, eu geralmente mudei para Protected (somente esta classe e classes derivadas podem alterar o valor) ou Friend (somente membros da minha assembly podem alterar o valor ).

Mas usar Privado faz muito sentido quando você quer fazer outras tarefas no setter além de alterar o valor de apoio. Como apontado anteriormente, é um bom design não referenciar seus valores de apoio diretamente, mas apenas acessá-los através de suas propriedades. Isso garante que as alterações posteriores feitas em uma propriedade sejam aplicadas internamente e externamente. E praticamente não há penalidade de desempenho para fazer referência a uma propriedade versus sua variável de apoio.

    
por 08.10.2012 / 15:16
fonte
-1

And there's virtually no performance penalty...

Mas, para esclarecer, o acesso a uma propriedade é mais lento do que acessar sua variável de apoio. O getter e setter de uma propriedade são métodos que requerem uma chamada e um retorno, enquanto a variável de apoio de uma propriedade é acessada diretamente.

É por isso que, nos casos em que o getter de uma propriedade pode ser acessado muitas vezes em um bloco de código, o valor da propriedade é armazenado primeiro em cache (salvo em uma variável local) e a variável local é usada. Naturalmente, isso pressupõe que a propriedade não possa ser alterada de forma assíncrona enquanto o bloco está sendo executado.

    
por 14.07.2014 / 14:56
fonte

Tags