Você deve criar propriedades particulares?


19
private string mWhatever;

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = value;
    }
}

Eu já vi algumas pessoas que fazem propriedades para cada membro, particular ou não ... isso faz algum sentido? Pude ver isso fazendo sentido em 1% dos casos, quando você deseja controlar o acesso ao membro dentro da classe que o contém, porque se você não usasse propriedades para cada membro, isso levaria a inconsistências e verificação para ver se o O membro tem ou não acesso (já que você tem acesso a ambos no escopo da classe).

Respostas:


17

Resposta curta: Sim , quando houver necessidade. Caso contrário, use um getter de propriedade implementada automaticamente e um setter comoprivate string Whatever { get; set;}

  • É muito útil Quando você está usando uma abordagem de domínio próximo
  • Também é útil quando uma lógica específica deve ser verificada ao definir o valor

Aqui está uma descrição completa de quando você usaria setters privados: uso da propriedade C # .


Também é realmente fácil tornar a propriedade pública mais tarde, se necessário.
21413 Tom Pickles

4
O que é uma abordagem de domínio próximo ?
Trisped

1
Eu estava me referindo a um levantador particular em uma propriedade da classe. Deve impedir o acesso direto para definir o valor do objeto e facilitar alguma verificação lógica antes de definir o valor.
Yusubov

ter variáveis ​​privadas com setter / getters públicos (mesmo que sejam apenas ingênuos) também tem a vantagem de que, se seu código for compilado em uma biblioteca, a assinatura permanecerá inalterada se você substituir seus setter / getters ingênuos por outros que tenham etc., mas se você usar uma variável pública simples, a assinatura da biblioteca será alterada se você a alterar para um setter / getters não ingênuo / privado. .. o que significaria que se sua biblioteca fosse alterada dessa maneira, os consumidores da sua biblioteca precisariam recompilar.
Orion elenzil 17/05/19

12

Algumas boas respostas aqui já, mas acho que a maioria delas perde um ponto da sua pergunta:

Eu já vi algumas pessoas que fazem propriedades para cada membro, particular ou não ... isso faz algum sentido?

Eu acho que isso raramente é necessário de antemão, para cada membro . Começar com

 private string Whatever;

Quando mais tarde você chega a um ponto em que precisa de encapsulamento ou um ponto de interrupção condicional para esse membro específico, ainda pode substituí-lo por uma propriedade com o mesmo nome - na maioria dos casos, sem alterar o código usado Whatever. Mas cuidado, existem diferenças sutis, veja a resposta de Brian Rasmussen neste post do SO (link também fornecido por Emmad Kareem, +1).


+1, também, você está correto, a maioria das respostas perdeu os pontos de interrogação originais, nós somos caras de TI típicos :)
NoChance

Refatorar um campo para uma propriedade após o fato é um pesadelo; exigindo que você recompile todos os consumidores. Alterar uma propriedade automática para conter a lógica personalizada é fácil. Se houver uma pequena chance do código ver o refator, será muito menos trabalhoso se você apenas usar propriedades desde o início.
1616 Dan

@ Dan: na maioria dos projetos, vi o esforço ser o mesmo, você deve recompilar nos dois casos. Não obstante, acho que você está certo de que o uso de propriedades, especialmente propriedades automáticas, pode ajudar a evitar alguns problemas sutis de reflexão ou o uso de variáveis-membro nos parâmetros "out".
Doc Brown

@ DocBrown De qualquer forma, definitivamente não é uma afirmação abrangente. Existem várias razões para simplificar e usar um campo. Se você pode prever um refator, porém, mesmo os problemas sutis são aqueles que vale a pena considerar.
21416 Dan

7

Uma das maiores vantagens dessa abordagem é que você controla quando suas variáveis ​​mudam .

Considere o seguinte.
Você está depurando um projeto grande. Um determinado método lança uma exceção. Você define um ponto de interrupção e revela que uma determinada variável de membro tem um valor incorreto. Digamos que seu código confie nessa variável muito extensivamente e você encontre centenas de usos de gravação ( cenário de espaguete ). Portanto, você não pode descobrir qual desses usos atribuiu um valor ruim.
Se o código for multithread, a depuração pode se tornar um pesadelo real.

Com a propriedade, você pode definir um ponto de interrupção em um setter . Combinado com uma condição, ele pode ser pregado em uma única execução.

O VC ++ possui pontos de interrupção de dados , mas está disponível apenas para código não gerenciado.


1

Se você não usar uma propriedade, sua única outra opção é usar um campo para armazenar dados variáveis. Propriedades e campos têm diferenças significativas. A maioria dessas diferenças são encontradas Campos vs. Propriedades . Sugiro que você estude as diferenças e faça sua escolha de acordo com as necessidades de sua aplicação. No entanto, lembre-se de que usar campos em vez de propriedades não é uma prática comum de OO devido à sua natureza e deficiências.


1

Propriedades particulares podem ser muito úteis para encapsular o comportamento de coisas internas à sua classe. Só porque eles são privados, não significa que você não deve tirar proveito do açúcar sintático que as propriedades lhe dão.


O exemplo dado é ruim, no entanto. Os getters e setters de propriedades do Boilerplate como este são quase sempre uma má ideia. Se você estiver usando o C # 3.0 ou posterior, as propriedades automáticas são uma ideia muito melhor:

private string Whatever { get; set; };

Isso é mais curto, mais limpo e muito mais legível. Na verdade, é pouco mais do que apenas declarar a variável de suporte.

Mais importante ainda, as propriedades automáticas podem ser convertidas em propriedades completas a qualquer momento, sem alterar a semântica do restante do programa! Portanto, se você precisar adicionar validação ou manipulação de erros, poderá fazê-lo facilmente.


Como sempre, sempre achei uma pena que você não pudesse ter uma propriedade somente leitura, impor apenas poder escrever no valor do construtor ( prefiro tipos imutáveis ), mas isso foi adicionado no C # 6.0 como "Inicializadores de propriedades automáticas", que permitem:

private string Whatever { get; } = ...;

ou

private string Whatever { get; };

junto com

    Whatever = ...;

no construtor.


0

Não é absolutamente necessário fazer isso para propriedades privadas, mas permite modificar como a propriedade obtém / define o valor subjacente sem alterar a maneira como é acessada.

Por exemplo, modificando como o valor subjacente é definido:

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
}

0

Sim

Eu pessoalmente uso isso como o mecanismo de cache, e podemos chamá-lo de cache no nível da propriedade .

private List<User> users;
private List<User> Users
{
    get
    {
        if(users == null) users = new UserManager().GetUsers();
        return users;
    }
}

Agora, em outros lugares da minha classe, uso Userspropriedade em vez de userscampo.

Outra situação viável pode ser quando você deseja implementar alguma lógica em um campo, mas de maneira centralizada em uma classe. Assim, você pode criar um GetFoo()método ou uma Foopropriedade para o foocampo.

private string foo;
private string Foo
{
    get
    {
        return "Mr. " + foo;
    }
}

0

Outra coisa a considerar:

As propriedades reais são um detalhe de implementação. Um dos objetivos do OOP é tentar minimizar a exposição dos detalhes da implementação sempre que possível.

A razão para isso é que, se você oculta as propriedades e as expõe apenas através de getters e setters, você tem muito mais controle. Por exemplo, seu getter pode validar sua entrada e impedir que a propriedade seja configurada para um estado inválido. Se a capacidade de alterar o valor for de tempo crítico, o levantador também poderá se proteger. O getter, caso o valor real seja caro por qualquer motivo, pode fazer uma inicialização lenta e / ou cache.

Ter getters e setters expostos e as propriedades ocultas significa que às vezes você não precisa de nenhuma propriedade. Seu getter pode calcular o valor na chamada, ou delegar a tarefa em outro lugar, ou qualquer coisa que permita atender às especificações. O que é importante sobre a sua turma é a informação que você pode acessar, e não como essa informação é representada internamente.

Obviamente, se não houver consequências negativas para algo fora da classe poder acessar uma propriedade diretamente, você deve torná-la pública. No entanto, na minha experiência, esses casos são relativamente poucos e distantes entre si.


0

Eu sei que essa é uma pergunta antiga e tudo o que o Yusubov disse está correto, mas com relação ao seu segundo ponto sobre lógica específica no setter, e como eu não vi ninguém mencionar isso especificamente, um exemplo perfeito seria quando sua classe implementa a INotifyPropertyChangedinterface.

Isso é usado bastante no WCF e no Silverlight, que permite saber quando uma propriedade específica foi alterada através da lógica em seu setter, como na classe abaixo:

public class Settings : INotifyPropertyChanged
{
    public Settings() 
    { 
        this.CountryField = String.Empty; 
    }

    private string CountryField;
    public string Country
    {
        get { return this.CountryField; }
        set
        {
            if (Object.ReferenceEquals(this.CountryField, value)) { return; }

            this.CountryField = value;
            this.RaisePropertyChanged("Country");
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.