Auto-propriedades do C # 3.0 – útil ou não?

Nota: Isso foi postado quando eu estava começando C #. Com o conhecimento de 2014, posso realmente dizer que as propriedades automáticas estão entre as melhores coisas que já aconteceram na linguagem C #.

Eu estou acostumado a criar minhas propriedades em C # usando um campo privado e público:

private string title; public string Title { get { return title; } set { title = value; } } 

Agora, com o .NET 3.0, obtivemos propriedades automáticas:

 public string Title { get; set; } 

Eu sei que isso é mais uma questão filosófica / subjetiva, mas existe alguma razão para usar essas propriedades auto exceto salvar cinco linhas de código para cada campo? Minha queixa pessoal é que essas propriedades estão escondendo coisas de mim, e eu não sou um grande fã de magia negra.

Na verdade, o campo privado oculto nem aparece no depurador, o que é OK, dado o fato de que as funções get / set não fazem nada. Mas quando eu quero realmente implementar alguma lógica getter / setter, eu tenho que usar o par privado / público de qualquer maneira.

Vejo o benefício de economizar muito código (uma contra seis linhas) sem perder a capacidade de alterar a lógica de getter / setter mais tarde, mas, novamente, já posso fazer isso simplesmente declarando um campo público “Public String Title” sem a necessidade do {get; conjunto; } bloquear, economizando ainda mais código.

Então, o que estou perdendo aqui? Por que alguém realmente quer usar propriedades automáticas?

   

Nós os usamos o tempo todo no Stack Overflow.

Você também pode estar interessado em uma discussão sobre Propriedades vs. Variáveis ​​Públicas . IMHO que é realmente o que esta é uma reação, e para esse fim, é ótimo.

Sim, apenas salva código. É milhas mais fácil de ler quando você tem um monte deles. Eles são mais rápidos para escrever e mais fáceis de manter. Salvar código é sempre um bom objective.

Você pode definir escopos diferentes:

 public string PropertyName { get; private set; } 

Assim, a propriedade só pode ser alterada dentro da class. Isso não é realmente imutável, pois você ainda pode acessar o setter privado por meio da reflection.

A partir do C # 6, você também pode criar propriedades true readonly – isto é, propriedades imutáveis ​​que não podem ser alteradas fora do construtor:

 public string PropertyName { get; } public MyClass() { this.PropertyName = "whatever"; } 

Em tempo de compilation, isso se tornará:

 readonly string pName; public string PropertyName { get { return this.pName; } } public MyClass() { this.pName = "whatever"; } 

Em classs imutáveis ​​com muitos membros, isso economiza muito excesso de código.

As três grandes desvantagens de usar campos em vez de propriedades são:

  1. Você não pode vincular a um campo enquanto você pode a uma propriedade
  2. Se você começar a usar um campo, não poderá mais tarde (facilmente) alterá-los para uma propriedade
  3. Existem alguns atributos que você pode adicionar a uma propriedade que você não pode adicionar a um campo

Eu pessoalmente adoro auto-propriedades. O que há de errado em salvar as linhas de código? Se você quiser fazer coisas em getters ou setters, não há problema em convertê-los em propriedades normais mais tarde.

Como você disse, você poderia usar campos e, se quisesse adicionar lógica a eles, convertê-los em propriedades. Mas isso pode apresentar problemas com qualquer uso de reflection (e possivelmente em outro lugar?).

Além disso, as propriedades permitem que você defina diferentes níveis de access para o getter e o setter, que você não pode fazer com um campo.

Eu acho que é o mesmo que a palavra-chave var. Uma questão de preferência pessoal.

De Bjarne Stroustrup, criador do C ++:

Eu particularmente não gosto de classs com muitas funções get e set. Isso é frequentemente uma indicação de que não deveria ter sido uma aula em primeiro lugar. É apenas uma estrutura de dados. E se for realmente uma estrutura de dados, faça uma estrutura de dados.

Você sabe o que? Ele tem razão. Com que frequência você simplesmente coloca campos privados em um get e set, sem realmente fazer nada dentro do get / set, simplesmente porque é a coisa “orientada a object” a ser feita. Esta é a solução da Microsoft para o problema; são basicamente campos públicos aos quais você pode se ligar.

Uma coisa que ninguém parece ter mencionado é como as auto-propriedades infelizmente não são úteis para objects imutáveis ​​(geralmente estruturas imutáveis). Porque para isso você realmente deveria fazer:

 private readonly string title; public string Title { get { return this.title; } } 

(onde o campo é inicializado no construtor por meio de um parâmetro passado e, em seguida, é somente leitura).

Portanto, isso tem vantagens em relação a uma autoproperty simples de get / private set .

Eu sempre criar propriedades em vez de campos públicos, porque você pode usar propriedades em uma definição de interface, você não pode usar campos públicos em uma definição de interface.

Auto-propriedades são tanto uma magia negra como qualquer outra coisa em C #. Uma vez que você pense sobre isso em termos de compilation para o IL em vez de ser expandido para uma propriedade C # normal, é muito menos magia negra do que muitas outras construções de linguagem.

Eu uso auto-propriedades o tempo todo. Antes de C # 3 eu não poderia ser incomodado com toda a digitação e apenas usei variables ​​públicas em vez disso.

A única coisa que sinto falta é poder fazer isso:

 public string Name = "DefaultName"; 

Você tem que mudar os padrões em seus construtores com propriedades. tedioso 🙁

Eu acho que qualquer constructo que é intuitivo e reduz as linhas de código é uma grande vantagem.

Esses tipos de resources fazem com que linguagens como o Ruby sejam tão poderosas (resources dynamics e que também ajudam a reduzir o excesso de código).

Ruby teve isso o tempo todo como:

 attr_accessor :my_property attr_reader :my_getter attr_writer :my_setter 

O único problema que tenho com eles é que eles não vão longe o suficiente. A mesma versão do compilador que adicionou propriedades automáticas, adicionou methods parciais. Por que eles não colocaram os dois juntos está além de mim. Um simples “partial On Changed” teria feito essas coisas realmente úteis.

É simples, é curto e se você quiser criar uma implementação real dentro do corpo da propriedade em algum lugar abaixo da linha, ela não quebrará a interface externa do seu tipo.

Tão simples como isso.

Uma coisa a notar aqui é que, no meu entender, isso é apenas açúcar sintático no final do C # 3.0, o que significa que o IL gerado pelo compilador é o mesmo. Eu concordo em evitar magia negra, mas mesmo assim, menos linhas para a mesma coisa geralmente é uma coisa boa.

Na minha opinião, você deve sempre usar propriedades automáticas em vez de campos públicos. Dito isto, aqui está um compromisso:

Comece com um campo interno usando a convenção de nomenclatura que você usaria para uma propriedade. Quando você primeiro

  • precisam de access ao campo de fora de sua assembly, ou
  • precisa append lógica a um getter / setter

Faça isso:

  1. renomear o campo
  2. torná-lo privado
  3. adicionar uma propriedade pública

Seu código de cliente não precisará ser alterado.

Algum dia, porém, seu sistema crescerá e você o decomporá em montagens separadas e várias soluções. Quando isso acontece, todos os campos expostos voltarão para assombrá-lo porque, como Jeff mencionou, alterar um campo público para uma propriedade pública é uma alteração na API .

Eu uso o CodeRush, é mais rápido que as propriedades automáticas.

Para fazer isso:

  private string title; public string Title { get { return title; } set { title = value; } } 

Requer oito teclas no total.

Bem, com trechos de código, uma propriedade automática com o mesmo nome seria de sete teclas no total;)

@Domenic: Eu não entendo .. você não pode fazer isso com auto-propriedades ?:

 public string Title { get; } 

ou

 public string Title { get; private set; } 

É isso que você está se referindo?

Minha maior queixa com as propriedades automáticas é que elas são projetadas para poupar tempo, mas muitas vezes eu acho que tenho que expandi-las para propriedades totalmente desenvolvidas mais tarde.

O que o VS2008 está faltando é um refator de Auto-Propriedade Explode .

O fato de termos um refatorador de campo encapsulado faz com que eu trabalhe mais rápido apenas para usar campos públicos.