Propriedades vs Métodos

135

Pergunta rápida: Quando você decide usar propriedades (em C #) e quando você decide usar métodos?

Estamos ocupados com esse debate e encontramos algumas áreas em que é discutível se devemos usar uma propriedade ou um método. Um exemplo é este:

public void SetLabel(string text)
{
    Label.Text = text;
}

No exemplo, Label é um controle em uma página ASPX. Existe um princípio que possa governar a decisão (neste caso) de tornar isso um método ou uma propriedade.

Aceito a resposta que é mais geral e abrangente, mas que também toca no exemplo que dei.

Trumpi
fonte
2
-1 esta pergunta foi feita e respondida antes: stackoverflow.com/questions/164527/…
Element
Os prós e contras do método / campo / propriedade podem gerar longos debates; algum uso geral para propriedades: quando você deseja campos particulares / protegidos, mas ao mesmo tempo deseja expô-los. Outro uso é ter não apenas instruções, mas também expressões (ações, se desejar), até if()verificações (conforme o MSDN). Mas isso é complicado, pois o usuário nem sempre está ciente do custo de processamento por trás do acesso a uma variável (propriedade) (ou seja, o código não está disponível) e, por razões de rigor, é necessário fazer um benchmark da propriedade. Ah, e um "bônus" que você não pode usar ponteiros com propriedades.
mireazma

Respostas:

146

Na seção Escolhendo entre propriedades e métodos das Diretrizes de design para o desenvolvimento de bibliotecas de classes:

Em geral, métodos representam ações e propriedades representam dados. As propriedades devem ser usadas como campos, o que significa que as propriedades não devem ser computacionalmente complexas ou produzir efeitos colaterais. Quando não violar as diretrizes a seguir, considere usar uma propriedade, e não um método, porque desenvolvedores menos experientes consideram as propriedades mais fáceis de usar.

Ken Browning
fonte
3
Embora eu concorde com muito disso, não acho que a parte dos efeitos colaterais esteja certa. Por exemplo, "Cor" é geralmente uma propriedade de um objeto e tem efeitos colaterais óbvios (alterando a cor de um objeto). Alterar propriedades tem o efeito colateral óbvio de alterar o estado do objeto.
Erik Funkenbusch 02/03/09
46
Mystere Man mudando de cor é o efeito desejado, não o efeito colateral. O efeito colateral é algo que não se destina à ação primária.
Muhammad Hasan Khan
2
@Mystere Man: definelty mudando a cor não é um efeito colateral, eu concordo completamente com esta resposta
Ahmed Said
2
"Porque desenvolvedores menos experientes consideram as propriedades mais fáceis de usar." - A meu ver, esse é o único motivo para expor propriedades. Mas estou certo?
Tsabo
2
Qual é a diferença na implementação interna de uma propriedade versus um método. Alguma coisa é enviada para a pilha de chamadas sempre que uma propriedade é usada? Caso contrário, como mais ele é tratado?
Praveen
57

Sim, se tudo o que você está fazendo é obter e configurar, use uma propriedade

Se você estiver fazendo algo complexo que pode afetar vários membros dos dados, um método é mais apropriado. Ou se o seu getter usa parâmetros ou se ele usa mais do que um parâmetro de valor.

No meio, há uma área cinza onde a linha pode ficar um pouco embaçada. Não existe uma regra rígida e rápida e pessoas diferentes às vezes discordam se algo deve ser uma propriedade ou um método. O importante é apenas ser (relativamente) consistente com a maneira como você faz (ou como sua equipe faz).

Eles são amplamente intercambiáveis, mas uma propriedade sinaliza ao usuário que a implementação é relativamente "simples". Ah, e a sintaxe é um pouco mais limpa.

De um modo geral, minha filosofia é que, se você começar a escrever um nome de método que comece com get ou set e aceite zero ou um parâmetro (respectivamente), é o principal candidato para uma propriedade.

cleto
fonte
1
Down-vote. Isso não está correto. A complexidade de um getter ou setter é encapsulada no código do getter / setter. Quão complexo não é relevante, nem é se "afeta vários membros dos dados". É verdade que parâmetros fora do padrão ou múltiplos exigirão um método, mas, caso contrário, essa resposta não será precisa.
Hal50000
A primeira frase explica tudo. Bravo.
SWIIWII
13

As propriedades são uma maneira de injetar ou recuperar dados de um objeto. Eles criam uma abstração sobre variáveis ​​ou dados dentro de uma classe. Eles são análogos aos getters e setters em Java.

Métodos encapsulam uma operação.

Em geral, uso propriedades para expor bits únicos de dados ou pequenos cálculos em uma classe, como imposto sobre vendas. Que é derivado do número de itens e seu custo em um carrinho de compras.

Uso métodos ao criar uma operação, como recuperar dados do banco de dados. Qualquer operação que possua partes móveis é candidata a um método.

No seu exemplo de código, eu o envolveria em uma propriedade se precisar acessá-lo fora da classe que contém:

public Label Title 
{
   get{ return titleLabel;}
   set{ titleLabel = value;}
}

Configurando o texto:

Title.Text = "Properties vs Methods";

Se eu estivesse apenas configurando a propriedade Text do Label, é assim que eu faria:

public string Title 
{
   get{ return titleLabel.Text;}
   set{ titleLabel.Text = value;}
}

Configurando o texto:

Title = "Properties vs Methods";
Chuck Conway
fonte
12

Se você estiver definindo uma propriedade real do seu objeto, use uma propriedade.

Se você estiver executando uma tarefa / funcionalidade, use um método.

No seu exemplo, é uma propriedade definida sendo definida.

Se, no entanto, sua funcionalidade era AppendToLabel, você usaria um método.

Robin Day
fonte
11

Pesquisando no MSDN, encontrei uma referência em Propriedades vs Métodos que fornece ótimas diretrizes para a criação de métodos:

  • A operação é uma conversão, como Object.ToString .
  • A operação é cara o suficiente para que você queira se comunicar com o usuário para que ele considere o armazenamento em cache do resultado.
  • Obter um valor de propriedade usando o acessador get teria um efeito colateral observável.
  • Ligar para o membro duas vezes seguidas produz resultados diferentes.
  • A ordem de execução é importante. Observe que as propriedades de um tipo devem poder ser definidas e recuperadas em qualquer ordem.
  • O membro é estático, mas retorna um valor que pode ser alterado.
  • O membro retorna uma matriz. As propriedades que retornam matrizes podem ser muito enganadoras. Geralmente é necessário retornar uma cópia da matriz interna para que o usuário não possa alterar o estado interno. Isso, associado ao fato de que um usuário pode facilmente assumir que é uma propriedade indexada, leva a um código ineficiente.
Gavin Miller
fonte
Concordo que isso faz sentido sempre que aplicável. Mas estou certo que o uso de propriedades via ligação XAML no WPF não deixa outra opção a não ser executar as ações apropriadas no setter? (especialmente em um novo SelectedItem para ComboBoxes, ListBoxes, etc.)
Nicolas
9

Você só precisa olhar para o próprio nome ... "Propriedade". O que isso significa? O dicionário o define de várias maneiras, mas, neste caso, "um atributo essencial ou distintivo ou a qualidade de uma coisa" se encaixa melhor.

Pense sobre o objetivo da ação. Você está, de fato, alterando ou recuperando "um atributo essencial ou distintivo"? No seu exemplo, você está usando uma função para definir uma propriedade de uma caixa de texto. Isso parece meio bobo, não é?

Propriedades são realmente funções. Todos eles são compilados para getXXX () e setXXX (). Apenas os esconde no açúcar sintático, mas é o açúcar que fornece um significado semântico ao processo.

Pense em propriedades como atributos. Um carro tem muitos atributos. Cor, MPG, Modelo, etc. Nem todas as propriedades são configuráveis, algumas são calculáveis.

Enquanto isso, um método é uma ação. GetColor deve ser uma propriedade. GetFile () deve ser uma função. Outra regra prática é que, se não alterar o estado do objeto, deve ser uma função. Por exemplo, CalculatePiToNthDigit (n) deve ser uma função, porque na verdade não está alterando o estado do objeto Math ao qual está anexado.

Talvez esteja divagando um pouco, mas realmente se resume a decidir quais são seus objetos e o que eles representam. Se você não consegue descobrir se deve ser uma propriedade ou função, talvez não importa qual.

Erik Funkenbusch
fonte
9

Simmanticamente propriedades são atributos de seus objetos. Métodos são comportamentos do seu objeto.

Label é um atributo e faz mais sentido torná-lo uma propriedade.

Em termos de programação orientada a objetos, você deve ter uma compreensão clara do que faz parte do comportamento e do que é apenas um atributo.

Carro {Cor, Modelo, Marca}

Um carro possui os atributos Cor, Modelo e Marca, portanto, não faz sentido ter um método SetColor ou SetModel porque, de forma símtica, não solicitamos que o Car defina sua própria cor.

Portanto, se você mapear a propriedade / método do caso para o objeto da vida real ou o examinar do ponto de vista simétrico, sua confusão realmente desaparecerá.

Muhammad Hasan Khan
fonte
4

Também grande vantagem para Propriedades é que o valor da propriedade pode ser visto no Visual Studio durante a depuração.

David Karlaš
fonte
3

Prefiro usar propriedades para adicionar / definir métodos com 1 parâmetro. Se os parâmetros forem maiores, use métodos.

abatishchev
fonte
3

As propriedades devem ser apenas um conjunto simples e obter um revestimento. Algo mais e realmente deve ser movido para um método. Código complexo sempre deve estar nos métodos.

Neil Bostrom
fonte
3

Eu só uso propriedades para acesso a variáveis, ou seja, obter e configurar variáveis ​​individuais ou obter e configurar dados nos controles. Assim que qualquer tipo de manipulação de dados é necessário / realizado, eu uso métodos.

Marcus L
fonte
3

Por uma questão de design, as propriedades representam dados ou atributos do objeto de classe, enquanto os métodos são ações ou comportamentos do objeto de classe.

No .Net, mundo, existem outras implicações do uso de Propriedades:

  • As propriedades são usadas na ligação de dados, enquanto os métodos get_ / set_ não.
  • Propriedades do usuário de serialização XML como mecanismo natural de serilização.
  • As propriedades são acessadas pelo controle PropertyGrid e pelo ICustomTypeDescriptor interno , que pode ser usado com eficiência se você estiver gravando uma biblioteca personalizada.
  • As propriedades são controladas por Atributos ; pode-se usá-lo com sabedoria para projetar softwares orientados a aspectos.

Equívocos (IMHO) sobre o uso das Propriedades:

  • Usado para expor pequenos cálculos: o bloco get do ControlDesigner.SelectionRules é executado em 72 linhas !!
  • Usado para expor estruturas de dados internas: Mesmo que uma propriedade não seja mapeada para um membro de dados interno, pode-se usá-la como propriedade, se for um atributo da sua classe. Viceversa, mesmo que não seja aconselhável um atributo das propriedades da sua classe, retorne uma matriz como membros de dados (em vez disso, métodos são usados ​​para retornar uma cópia profunda dos membros.)

No exemplo aqui, poderia ter sido escrito, com mais significado comercial como:

public String Title
{
    set { Label.Text = text; }
}
NileshChauhan
fonte
2

As propriedades são muito boas porque são acessíveis no designer visual do visual studio, desde que tenham acesso.

Eles costumam ser usados ​​quando você está apenas configurando e obtendo e, talvez, alguma validação que não acessa uma quantidade significativa de código. Cuidado, pois a criação de objetos complexos durante a validação não é simples.

Qualquer outra coisa é a maneira preferida.

Não se trata apenas de semântica. O uso inadequado das propriedades começa a ocorrer estranheza no designer visual do visual studio.

Por exemplo, eu estava obtendo um valor de configuração dentro de uma propriedade de uma classe. A classe de configuração realmente abre um arquivo e executa uma consulta sql para obter o valor dessa configuração. Isso causou problemas no meu aplicativo, onde o arquivo de configuração seria aberto e bloqueado pelo próprio visual studio, e não pelo meu aplicativo, porque não estava apenas lendo, mas escrevendo o valor da configuração (através do método setter). Para consertar isso, eu apenas tive que alterá-lo para um método.

Jeremy Edwards
fonte
1

Aqui está um bom conjunto de diretrizes para quando usar propriedades versus métodos de Bill Wagner

  • Use uma propriedade quando tudo isso for verdadeiro: os getters devem ser simples e, portanto, improváveis ​​de lançar exceções. Observe que isso não implica acesso à rede (ou banco de dados). Qualquer um pode falhar e, portanto, lançaria uma exceção.
  • Eles não devem ter dependências um do outro. Observe que isso incluiria a configuração de uma propriedade e a afetação de outra. (Por exemplo, definir a propriedade FirstName afetaria uma propriedade FullName somente leitura que compusesse as propriedades de nome e sobrenome, implica uma dependência)
  • Eles devem ser configuráveis ​​em qualquer ordem
  • O getter não tem um efeito colateral observável Observe que esta diretriz não exclui algumas formas de avaliação lenta em uma propriedade.
  • O método sempre deve retornar imediatamente. (Observe que isso exclui uma propriedade que faz uma chamada de acesso ao banco de dados, chamada de serviço da web ou outra operação semelhante).
  • Use um método se o membro retornar uma matriz.
  • Chamadas repetidas para o getter (sem código interveniente) devem retornar o mesmo valor.
  • Chamadas repetidas para o configurador (com o mesmo valor) não devem produzir diferença em uma única chamada.

  • O get não deve retornar uma referência às estruturas de dados internas (consulte o item 23). Um método pode retornar uma cópia detalhada e evitar esse problema.

* Retirado da minha resposta para uma pergunta duplicada.

Chris Ballance
fonte
As respostas mais votadas e aceitas aqui stackoverflow.com/a/1294189/1551 Por que o voto negativo?
22616 Chris Ballance
2
Sei que estou um pouco atrasado para a festa, mas esse voto negativo provavelmente ocorreu devido ao fato de você ter copiado sua resposta. Ao copiar e colar, você admitiu que essa pergunta era basicamente uma duplicata da outra. Como tal, você deve ter marcado como duplicado em vez de respondê-lo. Eu recomendo olhar para um artigo no Meta para saber como lidar com perguntas duplicadas.
Joshua
0

Isto é simples.

1: use a propriedade quando desejar que seus dados sejam validados antes de serem armazenados no campo. Portanto, dessa maneira, a propriedade fornece encapsulamento para seus campos. Como se você deixar seus campos, o usuário final público poderá atribuir qualquer valor que possa ou não ser válido de acordo com os requisitos de seus negócios, como a idade deve ser maior que 18. Portanto, antes que o valor seja armazenado no campo correspondente, precisamos verificar sua validade. Dessa maneira, as propriedades representam dados.

2: Use o método quando desejar executar alguma ação, como se você estivesse fornecendo alguns dados como parâmetro e seu método está processando com base nos valores fornecidos e retornando o valor processado como saída. Ou você deseja alterar o valor de algum campo por esse cálculo. "Desta forma, o método representa ação".

O marciano
fonte
-1

Eu venho de java e eu usei get .. set .. método por um tempo.

Quando escrevo código, não pergunto: "acessar esses dados é simples ou requer um processo pesado?" porque as coisas podem mudar (hoje, recuperar essa propriedade é simples, amanhã pode exigir algum ou mais processo).

Hoje eu tenho um método SetAge (int idade) amanhã também terei o método SetAge (data de nascimento) que calcula a idade usando a data de nascimento.

Fiquei muito decepcionado com o fato de o compilador transformar a propriedade em get e set, mas não considera meus métodos Get ... e Set .. os mesmos.

Marco Staffoli
fonte