Propriedades automáticas do C # 3.0 - útil ou não? [fechadas]


155

Nota: Isso foi publicado quando eu estava iniciando o 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 #.

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 há alguma razão para usar essas propriedades automáticas, exceto ao 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.

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

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

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


86
"Minha queixa pessoal é que essas propriedades estão escondendo coisas de mim, e eu não sou um grande fã de magia negra". Hã? Você está ciente de que o compilador esconde uma tonelada de você o tempo todo, certo? A menos que você esteja escrevendo assembly (ou mais precisamente, os 1 e 0 reais do seu código), TUDO que você escreve está ocultando coisas de você.
Charles Boyung

Respostas:



62

Sim, apenas salva o código. É muito mais fácil ler milhas quando você as carrega. Eles são mais rápidos de escrever e mais fáceis de manter. Salvar código é sempre uma boa meta.

Você pode definir diferentes escopos:

public string PropertyName { get; private set; }

Para que a propriedade só possa ser alterada dentro da classe. Isso não é realmente imutável, pois você ainda pode acessar o setter privado por meio de reflexão.

A partir do C # 6, você também pode criar readonlypropriedades verdadeiras - ou seja, propriedades imutáveis ​​que não podem ser alteradas fora do construtor:

public string PropertyName { get; }

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

Em tempo de compilação que se tornará:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

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


"Então você não perde nenhuma funcionalidade." como você os depura?
wal

2
@wal - o que há para depurar? Desse ponto de vista, você está basicamente lidando com variáveis ​​de membros.
Keith

6
@wal - Você pode colocar um ponto de interrupção neles, assim como você pode acessar uma variável de membro, apenas não pode entrar nelas. Mas por que você iria querer? O que as propriedades automáticas realmente fazem é trivial e gerado automaticamente, se você tiver bugs, é um lugar em que é extremamente improvável que eles estejam.
Keith

3
podemos precisar levar isso para fora de Keith. :)
wal

1
Mas ok, suponha que você tenha muitas chamadas de setter para myObj.Title ... você deseja ver onde o valor muda de "texto" para nulo, ou seja, um ponto de interrupção condicional. como você consegue isso? você não pode nem definir um ponto de interrupção no setter
28/10/10

45

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

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

7
"Se você começar a usar um campo, não poderá mais tarde (facilmente) alterá-lo para uma propriedade", desculpe, mas por quê?
Homam

6
@Homam Principalmente, qualquer código de consumidor que use reflexo em seus campos seria interrompido, pois eles teriam que mudar de usar FieldInfo para PropertyInfo.
WCWedin

8
@Homam Além disso, alterar um campo para uma propriedade quebra a compatibilidade binária, exigindo que todos os consumidores do campo recompilem.
Odrade

1
Além dos problemas de recompilação e reflexão, é muito fácil encapsular campos usando o Visual Studio: Ctrl-R + E permitirá transformar um campo em uma propriedade com getters / setters apropriados. (ou clique com o botão direito do mouse no campo, re-fatore, encapsule o campo).
JoeBrockhaus

Os campos @Hommam são lvalues ​​(são variáveis) e propriedades não. O material que pode ter sido compilado quando era um campo pode não ser quando é uma propriedade.
Mark

29

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

Como você disse, você pode usar campos e, se desejar adicionar lógica a eles posteriormente, os converterá em propriedades. Mas isso pode apresentar problemas com qualquer uso de reflexão (e possivelmente em outro lugar?).

Além disso, as propriedades permitem definir níveis de acesso diferentes para o getter e o setter, o 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.


29

De Bjarne Stroustrup, criador de C ++:

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

E sabe de uma coisa? Ele tem razão. Quantas vezes você está simplesmente agrupando campos privados em um get e set, sem fazer nada dentro do get / set, simplesmente porque é a coisa "orientada a objetos" a ser feita. Esta é a solução da Microsoft para o problema; eles são basicamente campos públicos aos quais você pode se associar.


2
Eu realmente acho que isso deveria ter mais pontos. Muitas pessoas vêem as propriedades automáticas como uma luz verde para escrever classes horrivelmente encapsuladas (ou nem sequer encapsuladas) que são pouco mais que um campo público glorificado. É claro que isso é mais um problema de como as pessoas usam a ferramenta e não com a própria ferramenta, mas acho importante mencionar ao discutir propriedades em geral.
Sara

18

Uma coisa que ninguém parece ter mencionado é como infelizmente as propriedades automáticas não são úteis para objetos imutáveis ​​(geralmente estruturas imutáveis). Porque para isso você realmente deve 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 sobre uma propriedade simples get/ private setautomática.


Se você tiver uma estrutura alterando qualquer propriedade, ela resultará em uma nova estrutura. Isso só seria um problema se você quisesse um tipo de referência internamente imutável - não vejo uma razão para precisar de um.
1311 Keith

@ Keith: Sua primeira frase parece factualmente incorreta.
Domenic

3
Não public string Title { get; private set; }resultaria exatamente na mesma coisa? Você seria capaz de mudá-lo de dentro da classe, em seguida, é claro, mas se você fizer isso você tem outros problemas ...: p
Svish

2
@Svish - por que o argumento somente leitura palavra-chave em C # nunca deve ser usado porque seu uso significaria que estávamos nos escondendo esses "problemas diferentes"
Zaid Masud

2
Só quero dizer que, de um tipo de visão de API externa, não faria muita diferença. E assim, as propriedades automáticas podem ser usadas, se desejado. A melhor coisa seria, evidentemente, se você poderia fazer algo assimpublic string Title { get; private readonly set; }
Svish

12

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


8

As propriedades automáticas são tanto uma magia negra quanto qualquer outra coisa em C #. Quando você pensa sobre isso em termos de compilação para IL, em vez de ser expandido para uma propriedade C # normal primeiro, é muito menos magia negra do que muitas outras construções de linguagem.


5

Eu uso propriedades automáticas o tempo todo. Antes do C # 3, eu não podia me incomodar com toda a digitação e apenas usava variáveis ​​públicas.

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

public string Name = "DefaultName";

Você precisa mudar os padrões para seus construtores com propriedades. tedioso :-(


4
Com os inicializadores de propriedades automáticas do C # 6, em breve você poderá fazer isso: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz

5

Eu acho que qualquer construção que seja intuitiva e reduza as linhas de código é uma grande vantagem.

Esses tipos de recursos são o que torna linguagens como Ruby tão poderosas (recursos dinâmicos e que também ajudam a reduzir o excesso de código).

Ruby sempre teve isso como:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

2

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 métodos parciais. Por que eles não juntaram os dois está além de mim. Um simples "parcial em <PropertyName> Changed" tornaria essas coisas realmente muito úteis.


Você pode colocar vários métodos parciais dentro de outro método. Criar um padrão automático de algum tipo para eles seria confuso.
Matthew Whited

2

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

Tão simples como isso.


1

Uma coisa a observar aqui é que, no meu entender, isso é apenas um açúcar sintático no final do C # 3.0, o que significa que a IL gerada pelo compilador é a mesma. Concordo em evitar a magia negra, mas, mesmo assim, menos linhas para a mesma coisa geralmente são boas.


1

Na minha opinião, você sempre deve 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ê quer

  • precisa acessar o campo de fora de sua montagem ou
  • precisa anexar lógica a um getter / setter

Faça isso:

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

O código do seu 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 de API de quebra .


0

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 pressionamentos de tecla no total.


5
Se eu pressionar CTRL e V, posso colar muitas e muitas coisas / muito rapidamente /, mas isso não a torna 'melhor'. Como isso responde à pergunta original?
JBRWilkinson

0

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


0

@Domenic: Eu não entendi .. você não pode fazer isso com propriedades automáticas ?:

public string Title { get; }

ou

public string Title { get; private set; }

É isso que você está se referindo?


Você pode (o último; o primeiro não será compilado), mas o campo não é imutável dentro do seu objeto.
Domenic

Palavra de cautela, apenas estruturas são imutáveis ​​quando sinalizadas somente leitura, as classes são simplesmente não atribuíveis.
Guvante 8/10/08

0

Minha maior preocupação com as propriedades automáticas é que elas são projetadas para economizar tempo, mas muitas vezes acho que preciso expandi-las para as propriedades completas posteriormente.

O que falta ao VS2008 é um refator de propriedade automática de explosão.

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

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.