Por que devo evitar o uso de Propriedades em C #?

102

Em seu excelente livro, CLR Via C #, Jeffrey Richter disse que não gosta de propriedades e recomenda não usá-las. Ele deu algum motivo, mas eu realmente não entendo. Alguém pode me explicar por que devo ou não usar propriedades? No C # 3.0, com propriedades automáticas, isso muda?

Como referência, adicionei as opiniões de Jeffrey Richter:

• Uma propriedade pode ser somente leitura ou somente gravação; o acesso ao campo é sempre legível e gravável. Se você definir uma propriedade, é melhor oferecer os métodos de acesso get e set.

• Um método de propriedade pode lançar uma exceção; o acesso de campo nunca lança uma exceção.

• Uma propriedade não pode ser passada como parâmetro out ou ref para um método; um campo pode. Por exemplo, o código a seguir não será compilado:

using System;
public sealed class SomeType
{
   private static String Name 
   {
     get { return null; }
     set {}
   }
   static void MethodWithOutParam(out String n) { n = null; }
   public static void Main()
   {
      // For the line of code below, the C# compiler emits the following:
      // error CS0206: A property or indexer may not
      // be passed as an out or ref parameter
      MethodWithOutParam(out Name);
   }
}

• Um método de propriedade pode levar muito tempo para ser executado; o acesso ao campo sempre é concluído imediatamente. Um motivo comum para usar propriedades é executar a sincronização do thread, o que pode interromper o thread para sempre e, portanto, uma propriedade não deve ser usada se a sincronização do thread for necessária. Nessa situação, um método é preferido. Além disso, se sua classe pode ser acessada remotamente (por exemplo, sua classe é derivada de System.MashalByRefObject), chamar o método de propriedade será muito lento e, portanto, um método é preferível a uma propriedade. Na minha opinião, as classes derivadas de MarshalByRefObject nunca devem usar propriedades.

• Se chamado várias vezes em uma linha, um método de propriedade pode retornar um valor diferente a cada vez; um campo retorna o mesmo valor todas as vezes. A classe System.DateTime tem uma propriedade Now somente leitura que retorna a data e hora atuais. Cada vez que você consultar essa propriedade, ela retornará um valor diferente. Isso é um erro, e a Microsoft deseja poder consertar a classe tornando o Now um método em vez de uma propriedade.

• Um método de propriedade pode causar efeitos colaterais observáveis; o acesso ao campo nunca o faz. Em outras palavras, um usuário de um tipo deve ser capaz de definir várias propriedades definidas por um tipo em qualquer ordem que ele escolher, sem perceber qualquer comportamento diferente no tipo.

• Um método de propriedade pode requerer memória adicional ou retornar uma referência a algo que não é realmente parte do estado do objeto, portanto, modificar o objeto retornado não tem efeito sobre o objeto original; a consulta de um campo sempre retorna uma referência a um objeto que é garantido como parte do estado do objeto original. Trabalhar com uma propriedade que retorna uma cópia pode ser muito confuso para os desenvolvedores e essa característica freqüentemente não é documentada.

Quan Mai
fonte
11
Eu possuo a 3ª edição de 'CLR via C #' e na página 242 o Sr. Richter diz que pessoalmente não gosta de propriedades, mas nunca recomenda não usá-las. Cite a versão do livro e o número da página onde você leu.
kirk.burleson de

Respostas:

173

A razão de Jeff para não gostar de propriedades é porque elas se parecem com campos - então os desenvolvedores que não entendem a diferença irão tratá-las como se fossem campos, presumindo que elas sejam baratas de executar, etc.

Pessoalmente, discordo dele neste ponto específico - acho que as propriedades tornam o código do cliente muito mais simples de ler do que as chamadas de método equivalentes. Concordo que os desenvolvedores precisam saber que as propriedades são basicamente métodos disfarçados - mas acho que educar os desenvolvedores sobre isso é melhor do que tornar o código mais difícil de ler usando métodos. (Em particular, tendo visto o código Java com vários getters e setters sendo chamados na mesma instrução, eu sei que o código C # equivalente seria muito mais simples de ler. A Lei de Demeter é muito boa em teoria, mas às vezes foo.Name.Lengthrealmente é a coisa certa a usar ...)

(E não, as propriedades implementadas automaticamente não mudam nada disso.)

Isso é um pouco como os argumentos contra o uso de métodos de extensão - posso entender o raciocínio, mas o benefício prático (quando usado com moderação) supera o lado negativo, na minha opinião.

Jon Skeet
fonte
Muito obrigado pela sua resposta! Sobre argumentos contra o uso de métodos de extensão: você está falando sobre algum tópico de Jeffrey Richter ou em abstrato?
abatishchev
@abatishchev: Era apenas um ponto geral sobre métodos de extensão. Não está diretamente relacionado às propriedades.
Jon Skeet,
Eu iria mais longe. Exceto pelo aspecto de performance, não vejo porque um programador deveria SABER se algo é um campo, ou uma propriedade. Ele deve pensá-lo como um atributo de instância que designa o ESTADO da instância do objeto, e a implementação do objeto deve cuidar de todas as modificações em seu estado (dentro do contrato da classe). Portanto, as propriedades também podem ser campos em alguns casos, ou se tornar campos em outros, se talvez um redesenho da implementação da classe seja feito. Então, decidir entre um campo ou uma propriedade é uma questão de quanta proteção o estado precisa para permanecer consistente.
TheBlastOne
1
@PatrickFromberg: Você perdeu uma grande quantidade de código que usa campos somente leitura, aparentemente. Não há nada que diga que as propriedades implicam mutabilidade. Freqüentemente, tenho campos somente leitura apoiando propriedades somente leitura - você acha que isso é uma coisa ruim?
Jon Skeet de
1
@Patrick: Não, traz o benefício de separar a API da implementação - você pode alterar posteriormente como a propriedade é calculada a partir do campo (por exemplo, para calcular duas propriedades relacionadas a partir de um campo).
Jon Skeet de
34

Bem, vamos considerar seus argumentos um por um:

Uma propriedade pode ser somente leitura ou somente gravação; o acesso ao campo é sempre legível e gravável.

Isso é uma vitória para as propriedades, pois você tem um controle de acesso mais refinado.

Um método de propriedade pode lançar uma exceção; o acesso de campo nunca lança uma exceção.

Embora isso seja verdade, você pode muito bem chamar um método em um campo de objeto não inicializado e ter uma exceção lançada.

• Uma propriedade não pode ser passada como parâmetro out ou ref para um método; um campo pode.

Justo.

• Um método de propriedade pode levar muito tempo para ser executado; o acesso ao campo sempre é concluído imediatamente.

Também pode demorar muito pouco tempo.

• Se chamado várias vezes em uma linha, um método de propriedade pode retornar um valor diferente a cada vez; um campo retorna o mesmo valor todas as vezes.

Não é verdade. Como você sabe que o valor do campo não mudou (possivelmente por outro segmento)?

A classe System.DateTime tem uma propriedade Now somente leitura que retorna a data e hora atuais. Cada vez que você consultar essa propriedade, ela retornará um valor diferente. Isso é um erro, e a Microsoft deseja poder consertar a classe tornando o Now um método em vez de uma propriedade.

Se for um erro, é um pequeno erro.

• Um método de propriedade pode causar efeitos colaterais observáveis; o acesso ao campo nunca o faz. Em outras palavras, um usuário de um tipo deve ser capaz de definir várias propriedades definidas por um tipo em qualquer ordem que ele escolher, sem perceber qualquer comportamento diferente no tipo.

Justo.

• Um método de propriedade pode requerer memória adicional ou retornar uma referência a algo que não é realmente parte do estado do objeto, portanto, modificar o objeto retornado não tem efeito sobre o objeto original; a consulta de um campo sempre retorna uma referência a um objeto que é garantido como parte do estado do objeto original. Trabalhar com uma propriedade que retorna uma cópia pode ser muito confuso para os desenvolvedores e essa característica freqüentemente não é documentada.

Muitos dos protestos poderiam ser feitos para os getters e setters de Java também - e nós os tivemos por um bom tempo sem tais problemas na prática.

Acho que a maioria dos problemas poderia ser resolvida com um melhor realce de sintaxe (ou seja, diferenciando propriedades de campos) para que o programador saiba o que esperar.

Hejazzman
fonte
3
"os problemas poderiam ser resolvidos com um melhor realce de sintaxe" : Com que frequência você usa campos públicos? Os campos privados geralmente têm um estilo diferente, por exemplo _field. Ou apenas em minúsculas field.
Steven Jeuris
18

Não li o livro e você não citou a parte que não entende, então terei de adivinhar.

Algumas pessoas não gostam de propriedades porque podem fazer seu código fazer coisas surpreendentes.

Se eu digitar Foo.Bar, as pessoas que lêem normalmente esperam que isso seja simplesmente acessando um campo membro da classe Foo. É uma operação barata, quase gratuita e determinística. Posso chamá-lo repetidamente e obter o mesmo resultado todas as vezes.

Em vez disso, com propriedades, pode realmente ser uma chamada de função. Pode ser um loop infinito. Pode abrir uma conexão de banco de dados. Ele pode retornar valores diferentes sempre que eu o acessar.

É um argumento semelhante ao motivo pelo qual Linus odeia C ++. Seu código pode surpreender o leitor. Ele odeia sobrecarga de operador: a + bnão significa necessariamente adição simples. Pode significar alguma operação extremamente complicada, assim como as propriedades do C #. Pode ter efeitos colaterais. Pode fazer qualquer coisa.

Honestamente, acho que esse é um argumento fraco. Ambas as línguas estão cheias de coisas assim. (Devemos evitar a sobrecarga de operadores em C # também? Afinal, o mesmo argumento pode ser usado lá)

Propriedades permitem abstração. Podemos fingir que algo é um campo regular e usá-lo como se fosse um, sem precisar nos preocupar com o que está acontecendo nos bastidores.

Isso geralmente é considerado uma coisa boa, mas obviamente depende do programador escrever abstrações significativas. Suas propriedades devem se comportar como campos. Eles não devem ter efeitos colaterais, eles não devem realizar operações caras ou inseguras. Queremos ser capazes de pensar neles como campos.

No entanto, tenho outro motivo para considerá-los menos que perfeitos. Eles não podem ser passados ​​por referência a outras funções.

Os campos podem ser passados ​​como ref, permitindo que uma função chamada acesse-os diretamente. As funções podem ser passadas como delegados, permitindo que uma função chamada acesse-a diretamente.

Propriedades ... não posso.

Isso é péssimo.

Mas isso não significa que as propriedades sejam más ou não devam ser usadas. Para muitos propósitos, eles são ótimos.

Jalf
fonte
3
Meu argumento é que você não deve assumir que é um campo para começar - porque se você estiver chamando de qualquer outra classe, você não deve ter acesso a campos não constantes de qualquer maneira, porque eles devem ser privados. (Há também a convenção de nomenclatura para informá-lo.)
Jon Skeet,
1
Sim, eu concordo. O argumento parece resumir-se a "Estou acostumado com essa sintaxe sendo usada apenas para campos. Portanto, estendê-la para cobrir outros casos é ruim". E a resposta óbvia é "Bem, acostume-se a cobrir outros casos então, e não será ruim". ;)
jalf
Desejo que as linguagens .net forneçam um meio padrão pelo qual uma classe exponha propriedades como refparâmetros; um membro (por exemplo Foo) de um formulário void Foo<T>(ActionByRef<Point,T> proc, ref T param)com um atributo especial e tem a transformação do compilador thing.Foo.X+=someVar;em Foo((ref Point it, ref int param)=>it.X += param, ref someVar);. Como o lambda é um delegado estático, nenhum fechamento seria necessário e o usuário de um objeto poderia usar qualquer local de armazenamento que apoiasse a propriedade como um refparâmetro genuíno (e poderia passá-lo para outros métodos como um refparâmetro).
supercat
Escrever o lambda manualmente produz um código-fonte de aparência realmente desagradável, mas é por isso que ter o compilador realizando a transformação seria útil. O código para uma classe expor uma propriedade "callback-by-ref" seria bastante razoável. O código é apenas feio (sem transformação) do lado do chamador.
supercat de
Por favor, entenda que uma propriedade é uma chamada de função disfarçada de membro, então ela não pode ser passada por referência da mesma forma que você não pode passar as funções públicas de uma classe. Você sempre pode usar membro público se quiser fazer isso dessa forma. Uma propriedade é um membro inteligente, ela pode lançar uma exceção para dados inválidos passados ​​para set.
Diceyus
17

Em 2009, esse conselho parecia apenas uma dor de barriga da variedade de Quem Mexeu no Meu Queijo . Hoje, está quase ridiculamente obsoleto.

Um ponto muito importante que muitas respostas parecem errar, mas não abordam de frente é que esses supostos "perigos" das propriedades são uma parte intencional do design da estrutura!

Sim, as propriedades podem:

  • Especifique diferentes modificadores de acesso para getter e setter. Esta é uma vantagem sobre os campos. Um padrão comum é ter um getter público e um setter protegido ou interno , uma técnica de herança muito útil que não pode ser alcançada apenas pelos campos.

  • Lance uma exceção. Até o momento, este continua sendo um dos métodos mais eficazes de validação, especialmente ao trabalhar com estruturas de IU que envolvem conceitos de vinculação de dados. É muito mais difícil garantir que um objeto permaneça em um estado válido ao trabalhar com campos.

  • Demora muito para executar. A comparação válida aqui é com métodos , que demoram igualmente - não campos . Nenhuma base é dada para a afirmação "um método é preferido", exceto a preferência pessoal de um autor.

  • Retorna valores diferentes de seu getter nas execuções subsequentes. Isso quase parece uma piada tão perto do ponto de exaltar as virtudes dos parâmetros ref/ outcom campos, cujo valor de um campo após uma chamada ref/ outé praticamente garantido ser diferente de seu valor anterior, e de forma imprevisível.

    Se estamos falando sobre o caso específico (e praticamente acadêmico) de acesso de thread único sem acoplamentos aferentes, é bastante entendido que é apenas um projeto de propriedade ruim ter efeitos colaterais de mudança de estado visível, e talvez minha memória esteja desaparecendo, mas simplesmente não consigo me lembrar de nenhum exemplo de pessoas usando DateTime.Nowe esperando o mesmo valor sempre. Pelo menos não em qualquer caso em que eles não teriam estragado tudo tão mal com uma hipotética DateTime.Now().

  • Causam efeitos colaterais observáveis ​​- que é, obviamente, precisamente a razão pela qual as propriedades foram inventadas como um recurso de linguagem em primeiro lugar. As próprias diretrizes de design de propriedade da Microsoft indicam que a ordem do setter não deve importar, pois fazer o contrário implicaria em acoplamento temporal . Certamente, você não pode alcançar o acoplamento temporal com os campos sozinho, mas isso apenas porque você não pode causar nenhum comportamento significativo para acontecer com os campos sozinho, até que algum método seja executado.

    Os acessadores de propriedade podem ajudar a prevenir certos tipos de acoplamento temporal, forçando o objeto a um estado válido antes que qualquer ação seja executada - por exemplo, se uma classe tem um StartDatee um EndDate, então definir o EndDateantes de também StartDatepode forçar o StartDateretorno. Isso é verdadeiro mesmo em ambientes multithread ou assíncronos, incluindo o exemplo óbvio de uma interface de usuário orientada a eventos.

Outras coisas que as propriedades podem fazer e os campos não podem incluir:

  • Carregamento lento , uma das maneiras mais eficazes de evitar erros de ordem de inicialização.
  • Notificações de mudança , que são praticamente toda a base para a arquitetura MVVM .
  • Herança , por exemplo, definir classes abstratas Typeou Namederivadas pode fornecer metadados interessantes, mas constantes sobre si mesmas.
  • Interceptação , graças ao acima.
  • Indexadores , que todos que já tiveram que trabalhar com interoperabilidade COM e o inevitável aumento de Item(i)chamadas, reconhecerão como algo maravilhoso.
  • Trabalhe com PropertyDescriptor, que é essencial para a criação de designers e para estruturas XAML em geral.

Richter é claramente um autor prolífico e sabe muito sobre CLR e C #, mas devo dizer que parece que foi quando ele escreveu este conselho originalmente (não tenho certeza se está em suas revisões mais recentes - sinceramente espero que não) que ele simplesmente não queria abandonar os velhos hábitos e estava tendo problemas para aceitar as convenções do C # (vs. C ++, por exemplo).

O que quero dizer com isso é que seu argumento de "propriedades consideradas prejudiciais" essencialmente se resume a uma única declaração: as propriedades parecem campos, mas podem não agir como campos. E o problema com a afirmação é que não é verdade ou, na melhor das hipóteses, é altamente enganosa. Propriedades não se parecem com campos - pelo menos, elas não deveriam se parecer com campos.

Existem duas convenções de codificação muito fortes em C # com convenções semelhantes compartilhadas por outras linguagens CLR, e FXCop gritará com você se você não segui-las:

  1. Os campos devem ser sempre privados, nunca públicos.
  2. Os campos devem ser declarados em camelCase. As propriedades são PascalCase.

Assim, não há ambigüidade sobre se Foo.Bar = 42é um acessador de propriedade ou um acessador de campo. É um acessador de propriedade e deve ser tratado como qualquer outro método - pode ser lento, pode lançar uma exceção, etc. Essa é a natureza de Abstraction - fica inteiramente a critério da classe declarante como reagir. Os projetistas de classe devem aplicar o princípio da menor surpresa, mas os chamadores não devem presumir nada sobre uma propriedade, exceto que ela faz o que diz na lata. Isso é de propósito.

A alternativa às propriedades são os métodos getter / setter em todos os lugares. Essa é a abordagem Java e tem sido controversa desde o início . Tudo bem se essa for a sua, mas não é assim que atuamos no campo .NET. Tentamos, pelo menos dentro dos limites de um sistema estaticamente tipado, evitar o que Fowler chama de ruído sintático . Não queremos parênteses extras, extras get/ setverrugas ou assinaturas de métodos extras - não se pudermos evitá-los sem qualquer perda de clareza.

Diga o que quiser, mas foo.Bar.Baz = quux.Answers[42]sempre será muito mais fácil de ler do que foo.getBar().setBaz(quux.getAnswers().getItem(42)). E quando você está lendo milhares de linhas disso por dia, faz diferença.

(E se a sua resposta natural ao parágrafo acima for dizer, "claro que é difícil de ler, mas seria mais fácil se você dividisse em várias linhas", então lamento dizer que você perdeu completamente o ponto .)

Aaronaught
fonte
11

Não vejo nenhum motivo pelo qual você não deve usar Propriedades em geral.

As propriedades automáticas em C # 3+ apenas simplificam um pouco a sintaxe (a la açúcar sintático).

Konstantin Tarkus
fonte
por favor, leia as páginas 215-216 desse livro. Tenho certeza que você sabe quem é Jeffrey Richter!
Quan Mai,
Eu li (CLR via C #, 2ª Ed.), Não concordo com a posição dele e não vejo motivos reais para não usar propriedades!
abatishchev
É um bom livro, mas não concordo com o autor neste momento.
Konstantin Tarkus,
Onde é exatamente aquele lugar onde o autor sugere não usar Propriedades? Não encontrei nada em p.215-217
Konstantin Tarkus
Eu adicionei as opiniões de Jeffrey na minha pergunta :). Você pode encontrá-lo nas páginas 215-216 da edição impressa :)
Quan Mai
9

É a opinião de apenas uma pessoa. Eu li alguns livros c # e ainda não vi ninguém dizendo "não use propriedades".

Pessoalmente, acho que as propriedades são uma das melhores coisas sobre c #. Eles permitem que você exponha o estado por meio de qualquer mecanismo que desejar. Você pode instanciar preguiçosamente a primeira vez que algo é usado e pode fazer a validação na definição de um valor, etc. Ao usá-los e gravá-los, eu apenas penso nas propriedades como setters e getters, que são uma sintaxe muito mais agradável.

Quanto às ressalvas com propriedades, há algumas. Provavelmente, um deles é o uso indevido de propriedades, o outro pode ser sutil.

Em primeiro lugar, propriedades são tipos de métodos. Pode ser surpreendente se você colocar uma lógica complicada em uma propriedade porque a maioria dos usuários de uma classe espera que a propriedade seja bastante leve.

Por exemplo

public class WorkerUsingMethod
{
   // Explicitly obvious that calculation is being done here
   public int CalculateResult()
   { 
      return ExpensiveLongRunningCalculation();
   }
}

public class WorkerUsingProperty
{
   // Not at all obvious.  Looks like it may just be returning a cached result.
   public int Result
   {
       get { return ExpensiveLongRunningCalculation(); }
   }
}

Acho que usar métodos para esses casos ajuda a fazer uma distinção.

Em segundo lugar, e mais importante, as propriedades podem ter efeitos colaterais se você avaliá-las durante a depuração.

Digamos que você tenha alguma propriedade como esta:

public int Result 
{ 
   get 
   { 
       m_numberQueries++; 
       return m_result; 
   } 
}

Agora, suponha que você tenha uma exceção que ocorre quando muitas consultas são feitas. Adivinhe o que acontece quando você inicia a depuração e faz o rollover da propriedade no depurador? Coisas ruins. Evite fazer isso! Olhar para a propriedade muda o estado do programa.

Estas são as únicas ressalvas que tenho. Acho que os benefícios das propriedades superam em muito os problemas.

Mark Simpson
fonte
6

Essa razão deve ter sido dada dentro de um contexto muito específico. Geralmente é o contrário - é recomendado usar propriedades, pois elas fornecem um nível de abstração que permite alterar o comportamento de uma classe sem afetar seus clientes ...

Rashack
fonte
+1 para destacar implicitamente a importância do "contrato" entre o cliente e a propriedade da classe.
TheBlastOne
6

Não posso deixar de insistir nos detalhes das opiniões de Jeffrey Richter:

Uma propriedade pode ser somente leitura ou somente gravação; o acesso ao campo é sempre legível e gravável.

Errado: os campos podem ser marcados como somente leitura para que apenas o construtor do objeto possa gravar neles.

Um método de propriedade pode lançar uma exceção; o acesso de campo nunca lança uma exceção.

Errado: a implementação de uma classe pode alterar o modificador de acesso de um campo de público para privado. As tentativas de ler campos privados em tempo de execução sempre resultarão em uma exceção.

Cecil Tem Nome
fonte
5

Não concordo com Jeffrey Richter, mas posso imaginar por que ele não gosta de propriedades (não li seu livro).

Mesmo assim, as propriedades são como métodos (em termos de implementação), como um usuário de uma classe, espero que suas propriedades se comportem "mais ou menos" como um campo público, por exemplo:

  • não há operação demorada acontecendo dentro do getter / setter de propriedade
  • o getter de propriedade não tem efeitos colaterais (chamá-lo várias vezes, não altera o resultado)

Infelizmente, tenho visto propriedades que não se comportam dessa forma. Mas o problema não são as propriedades em si, mas as pessoas que as implementaram. Portanto, requer apenas um pouco de educação.

M4N
fonte
1
+1, pois destaca a importância de um contrato limpo. Ter uma propriedade aparentemente somente leitura que retorna regularmente um valor diferente em cada referência é uma propriedade readwrite - ela simplesmente não grava em seu próprio valor, mas em outras variáveis ​​de instância (direta ou indiretamente). Isso não é um estilo ruim, mas deve ser documentado (ou ser uma parte implícita do contrato).
TheBlastOne
4

Há um momento em que considero não usar propriedades, e isso ocorre ao escrever o código do .Net Compact Framework. O compilador CF JIT não executa a mesma otimização que o compilador JIT de desktop e não otimiza acessadores de propriedade simples, portanto, neste caso, adicionar uma propriedade simples causa um pequeno volume de código sobre o uso de um campo público. Normalmente, isso não seria um problema, mas quase sempre no mundo do Compact Framework você enfrenta fortes restrições de memória, portanto, mesmo pequenas economias como essa contam.

Steve
fonte
4

Você não deve evitar usá-los, mas deve usá-los com qualificação e cuidado, pelas razões apresentadas por outros contribuidores.

Certa vez, vi uma propriedade chamada algo como Clientes que abriu internamente uma chamada fora do processo para um banco de dados e leu a lista de clientes. O código do cliente tinha um 'for (int i to Customers.Count)' que estava causando uma chamada separada para o banco de dados em cada iteração e para o acesso do Cliente selecionado. Esse é um exemplo flagrante que demonstra o princípio de manter a propriedade muito leve - raramente mais do que um acesso de campo interno.

Um argumento para o uso de propriedades é que elas permitem que você valide o valor que está sendo definido. Outra é que o valor de da propriedade pode ser um valor derivado, não um único campo, como TotalValue = quantidade * quantidade.

Rob Kent
fonte
3

Pessoalmente, só uso propriedades ao criar métodos get / set simples. Eu me afasto disso quando chego a estruturas de dados complicadas.

Steve
fonte
3

O argumento pressupõe que as propriedades são ruins porque se parecem com campos, mas podem realizar ações surpreendentes. Esta suposição é invalidada pelas expectativas dos programadores .NET:

As propriedades não se parecem com campos. Os campos parecem propriedades.

• Um método de propriedade pode lançar uma exceção; o acesso de campo nunca lança uma exceção.

Portanto, um campo é como uma propriedade que nunca lançará uma exceção.

• Uma propriedade não pode ser passada como parâmetro out ou ref para um método; um campo pode.

Portanto, um campo é como uma propriedade, mas tem recursos adicionais: passar para métodos a ref/ outaccept.

• Um método de propriedade pode levar muito tempo para ser executado; o acesso ao campo sempre é concluído imediatamente. [...]

Portanto, um campo é como uma propriedade rápida.

• Se chamado várias vezes em uma linha, um método de propriedade pode retornar um valor diferente a cada vez; um campo retorna o mesmo valor todas as vezes. A classe System.DateTime tem uma propriedade Now somente leitura que retorna a data e hora atuais.

Portanto, um campo é como uma propriedade que tem garantia de retornar o mesmo valor, a menos que o campo tenha sido definido com um valor diferente.

• Um método de propriedade pode causar efeitos colaterais observáveis; o acesso ao campo nunca o faz.

Novamente, um campo é uma propriedade que certamente não fará isso.

• Um método de propriedade pode requerer memória adicional ou retornar uma referência a algo que não é realmente parte do estado do objeto, portanto, modificar o objeto retornado não tem efeito sobre o objeto original; a consulta de um campo sempre retorna uma referência a um objeto que é garantido como parte do estado do objeto original. Trabalhar com uma propriedade que retorna uma cópia pode ser muito confuso para os desenvolvedores e essa característica freqüentemente não é documentada.

Este pode ser surpreendente, mas não porque é uma propriedade que faz isso. Em vez disso, quase ninguém retorna cópias mutáveis ​​em propriedades, de modo que 0,1% do caso é surpreendente.

milênio
fonte
0

Chamar métodos em vez de propriedades reduz muito a legibilidade do código de chamada. Em J #, por exemplo, usar ADO.NET era um pesadelo porque Java não oferece suporte a propriedades e indexadores (que são essencialmente propriedades com argumentos). O código resultante era extremamente feio, com chamadas de método de parênteses vazias por toda parte.

O suporte para propriedades e indexadores é uma das vantagens básicas do C # em relação ao Java.

Marty Solomon
fonte