Variável privada vs propriedade?

41

Ao definir um valor para uma variável dentro de uma classe na maioria das vezes, somos apresentados a duas opções:

private string myValue;
public string MyValue
{
   get { return myValue; }
   set { myValue = value; }
}

Existe uma convenção que determina como devemos atribuir valores a variáveis dentro de nossas classes? Por exemplo, se eu tiver um método dentro da mesma classe, devo atribuí-lo usando a propriedade ou usando a variável privada. Eu vi isso feito das duas maneiras, então eu estava me perguntando se isso é uma escolha ou se o desempenho é um fator (menor, provavelmente).

    
por Edward 02.02.2012 / 18:21
fonte

8 respostas

22

Eu levaria isso um passo além e traria para 3 casos. Embora existam variações em cada uma, estas são as regras que eu uso na maioria das vezes quando a programação C #.

No caso 2 e 3, sempre vá para o Property Accessor (não a variável de campo). E no caso 1, você está salvo de ter que fazer essa escolha.

1.) Propriedade imutável (passada para o construtor ou criada no momento da construção). Neste caso, eu uso uma variável de campo, com uma propriedade somente leitura. Eu escolho isso sobre um setter privado, já que um setter privado não garante a imutabilidade.

public class Abc
{ 
  private readonly int foo;

  public Abc(int fooToUse){
    foo = fooToUse;
  }

  public int Foo { get{ return foo; } }
}

2.) variável POCO. Uma variável simples que pode obter / definir em qualquer escopo público / privado. Neste caso, eu usaria apenas uma propriedade automática.

public class Abc
{ 
  public int Foo {get; set;}
}

3.) Propriedades de vinculação do ViewModel. Para classes que suportam INotifyPropertyChanged, acho que você precisa de uma variável de campo de apoio privada.

public class Abc : INotifyPropertyChanged
{
  private int foo;

  public int Foo
  {
    get { return foo; }
    set { foo = value;  OnPropertyChanged("foo"); }
  }
}
    
por 02.02.2012 / 19:21
fonte
18

Geralmente, eu diria atribuir ao campo no construtor e usar a propriedade em qualquer outro lugar. Dessa forma, se alguém adicionar funcionalidade à propriedade, você não sentirá falta dela em nenhum lugar.

Certamente não é um fator de desempenho. O otimizador irá embutir um get ou set simples para você e o código MSIL final provavelmente será idêntico.

    
por 02.02.2012 / 18:32
fonte
4

Depende.

Primeiro, você deve preferir as propriedades automáticas quando possível:

public string MyValue {get;set;}
Segundo, a melhor abordagem seria provavelmente usar as propriedades, se você tem alguma lógica, provavelmente deveria estar passando por ela, especialmente se essa lógica é a sincronização de threads.

Mas você também deve levar em conta que isso pode atrapalhar seu desempenho (um pouquinho), se você estiver sincronizando incorretamente você pode se travar, e em algum momento o caminho correto é contornar a lógica da propriedade.

    
por 02.02.2012 / 18:34
fonte
3

Bem, a abordagem direta é apenas atribuí-la à variável em si, já que você está dentro de um método de classe e controla o comportamento da classe, de qualquer forma.

Mas a questão toda sobre as propriedades é que abstraem a variável. Considerando que uma propriedade tão simples como em seu exemplo não tem nenhum uso sobre uma simples variável de membro público, as propriedades geralmente fazem (ou deveriam fazer) coisas adicionais dentro de seus getters e setters. E se você quiser que essas coisas sejam feitas automaticamente ao alterar a propriedade dentro da classe, é claro que é mais limpo trabalhar na propriedade em vez da variável para não precisar alterar cada atribuição de variável quando o comportamento da configuração da propriedade for alterado.

Você apenas tem que raciocinar sobre isso conceitualmente. A propriedade é realmente um identificador para acessar algum estado interno do objeto, que pode ser composto por mais de uma variável de membro. Então você tem que se perguntar se você quer mudar apenas o estado interno subjacente (ou apenas parte dele) ou a propriedade abstract representando este estado em um todo, e na maioria das vezes é o último pois você geralmente quer que seu objeto sempre tenha um estado consistente.

    
por 02.02.2012 / 18:38
fonte
2

Se houver alguma chance de que a implementação get / set dessa propriedade seja alterada algumas vezes mais tarde (por exemplo, você deseja aumentar um evento ao chamar set ou você adicionará um mecanismo de avaliação posterior à sua função get ), então pode ser uma boa ideia que seu código dentro da classe usará a propriedade em quase todos os casos, exceto nos casos - provavelmente mais raros - em que você explicitamente não quer esses eventos ou lazy mecanismos de avaliação a serem utilizados.

De qualquer forma, o que você fizer, há uma boa chance de que quando você alterar a implementação da propriedade mais tarde, você terá que verificar se todos os locais dentro de sua classe acessam essas propriedades para verificar se realmente a propriedade deve ser acessado ou a variável privada deve ser usada.

    
por 02.02.2012 / 18:32
fonte
2

Eu sempre uso a propriedade pública.

Geralmente, alguma lógica que sempre deve ser executada quando a propriedade é definida é adicionada ao método set de uma propriedade e, ao invés disso, o campo privado é ignorado por qualquer lógica.

Você tem um comentário sobre o MVVM que leva a essa pergunta, e acho que isso é ainda mais importante ao trabalhar com o MVVM. Muitos objetos geram uma notificação PropertyChange do setter e outros objetos podem se inscrever nesse evento para executar alguma ação quando propriedades específicas são alteradas. Se você definir a variável privada, essas ações nunca serão executadas, a menos que você também eleve manualmente o evento PropertyChanged .

    
por 02.02.2012 / 19:53
fonte
1

Geralmente, cabe a você o que você deve fazer com uma propriedade e seu campo de apoio ao obter / definir.

Na maioria das vezes, para ser consistente em todo o código, você deve usar os acessadores públicos onde quer que estejam disponíveis e sejam apropriados. Isso permite refatorar com uma alteração mínima de código; Se o método que faz esta configuração precisar ser retirado da classe e colocado em algum outro lugar onde o campo de apoio não esteja mais disponível (como uma classe base), quem se importa? Você está usando algo disponível onde quer que a classe esteja para fazer o trabalho. O campo de apoio, na maioria dos casos, é um detalhe de implementação; ninguém de fora da sua turma deve saber que existe.

A situação principal em que posso pensar quando você deve usar o campo de apoio e NÃO o acessador de propriedade é quando o acessador possui uma lógica adicional (validação ou atualização de outras informações de estado na classe) que você não deseja executar. População inicial de um objeto é um exemplo; você pode ter uma classe que usa dois valores de propriedade para calcular um terceiro, que também é armazenado em um campo de apoio (por motivos de persistência). Ao inicializar uma nova cópia desse objeto dados dados do banco de dados, os acessores da propriedade que cada um recalcular o terceiro valor pode reclamar se o outro valor necessário não estiver definido. Usando os campos de apoio para definir os valores iniciais dessas duas (ou três) propriedades, você ignora a lógica de validação / cálculo até que a instância esteja em um estado consistente para que a lógica funcione normalmente.

    
por 02.02.2012 / 20:35
fonte
0

Sempre use o que faz sentido. Sim, eu sei que isso soa muito falso a ponto de ser uma não-resposta.

O ponto das propriedades é fornecer uma interface através da qual você possa acessar com segurança um modelo de dados. Para a maioria das situações, você sempre deseja acessar com segurança o modelo de dados por meio dessa interface, como:

public Foo Bar
{
  get { return _bar; }
  set { _bar = doSomethingTo(value); }
}

Mas, em outras situações, você pode simplesmente usar uma propriedade como visualização de um modelo de dados:

public Double SomeAngleDegrees
{
  get { return SomeAngleRadians * 180 / PI; }
  set { SomeAngleRadians = value * PI / 180; }
}

Se fizer sentido usar a forma radianos de SomeAngle , use-a por todos os meios.

No final, não deixe de beber seu próprio kool-aid. Sua API voltada para o público deve ser resiliente o suficiente para funcionar internamente.

    
por 03.02.2012 / 02:45
fonte