Compartilhar via


Design de propriedade

Observação

Este conteúdo é reimpresso com permissão da Pearson Education, Inc. de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Essa edição foi publicada em 2008 e, desde então, o livro foi totalmente revisado na terceira edição. Algumas das informações nesta página podem estar desatualizadas.

Embora as propriedades sejam tecnicamente muito semelhantes aos métodos, elas são bem diferentes em termos de seus cenários de uso. Elas devem ser vistas como campos inteligentes. Elas têm a sintaxe de chamada dos campos e a flexibilidade dos métodos.

✔️ CRIE propriedades somente get se o chamador não puder alterar o valor da propriedade.

Saiba que, se o tipo da propriedade for um tipo de referência mutável, o valor da propriedade poderá ser alterado mesmo que a propriedade seja somente get.

❌ NÃO forneça propriedades somente set ou propriedades com um setter que tenha acessibilidade mais ampla do que o getter.

Por exemplo, não use propriedades com um setter público e um getter protegido.

Se o getter da propriedade não puder ser fornecido, implemente a funcionalidade como um método. Considere iniciar o nome do método com Set e seguir com o que você teria usado como nome da propriedade. Por exemplo, AppDomain tem um método chamado SetCachePath, em vez de ter uma propriedade somente set chamada CachePath.

✔️ FORNEÇA valores padrão concretos para todas as propriedades, garantindo que os padrões não resultem em uma brecha de segurança ou código extremamente ineficiente.

✔️ PERMITA que as propriedades sejam definidas em qualquer ordem, mesmo que isso resulte em um estado temporário inválido do objeto.

É comum que duas ou mais propriedades estejam inter-relacionadas com um ponto em que alguns valores de uma propriedade podem ser inválidos, considerando os valores de outras propriedades no mesmo objeto. Nesses casos, exceções resultantes do estado inválido devem ser adiadas até que as propriedades inter-relacionadas sejam de fato usadas juntas pelo objeto.

✔️ PRESERVE o valor anterior se um setter de propriedade gerar uma exceção.

❌ EVITE gerar exceções de getters de propriedade.

Os getters de propriedade devem ser operações simples e não devem ter pré-condições. Se um getter puder gerar uma exceção, ele provavelmente deverá ser reprojetado para ser um método. Observe que essa regra não se aplica aos indexadores, em que esperamos exceções como resultado da validação dos argumentos.

Design de propriedade indexada

Uma propriedade indexada é uma propriedade especial que pode ter parâmetros e ser chamada com sintaxe especial semelhante à indexação de matriz.

As propriedades indexadas são comumente conhecidas como indexadores. Os indexadores devem ser usados apenas em APIs que dão acesso a itens em uma coleção lógica. Por exemplo, uma cadeia de caracteres é uma coleção de caracteres e o indexador System.String foi adicionado para acessar seus caracteres.

✔️ CONSIDERE usar indexadores para dar acesso aos dados armazenados em uma matriz interna.

✔️ CONSIDERE fornecer indexadores em tipos que representam coleções de itens.

❌ EVITE usar propriedades indexadas com mais de um parâmetro.

Se o design exigir vários parâmetros, reconsidere se a propriedade realmente representa um acessador para uma coleção lógica. Caso não represente, use métodos. Considere iniciar o nome do método com Get ou Set.

❌ EVITE indexadores com tipos de parâmetro que não System.Int32, System.Int64, System.String, System.Object ou uma enumeração.

Se o design exigir outros tipos de parâmetros, avalie fortemente se a API realmente representa um acessador para uma coleção lógica. Se isso não acontecer, use um método. Considere iniciar o nome do método com Get ou Set.

✔️ Use o nome Item para propriedades indexadas, a menos que haja um nome obviamente melhor (por exemplo, confira a propriedade Chars[] em System.String).

Em C#, os indexadores são, por padrão, chamados Item. O IndexerNameAttribute pode ser usado para personalizar esse nome.

❌ NÃO forneça um indexador e métodos semanticamente equivalentes.

❌ NÃO forneça mais de uma família de indexadores sobrecarregados em um tipo.

Isso é imposto pelo compilador C#.

❌ NÃO use propriedades indexadas não padrão.

Isso é imposto pelo compilador C#.

Eventos de notificação de alteração de propriedade

Às vezes, é útil fornecer um evento notificando o usuário de alterações em um valor da propriedade. Por exemplo, System.Windows.Forms.Control gera um evento TextChanged depois que o valor de sua propriedade Text é alterado.

✔️ CONSIDERE gerar eventos de notificação de alteração quando os valores de propriedade em APIs de alto nível (geralmente componentes de designer) são modificados.

Se houver um bom cenário para um usuário saber quando uma propriedade de um objeto está mudando, o objeto deverá gerar um evento de notificação de alteração para a propriedade.

No entanto, é improvável que valha a pena a sobrecarga para gerar esses eventos para APIs de baixo nível, como tipos de base ou coleções. Por exemplo, List<T> não geraria esses eventos quando um novo item é adicionado à lista e a propriedade Count é alterada.

✔️ CONSIDERE gerar eventos de notificação de alteração quando o valor de uma propriedade é alterado por forças externas.

Se um valor da propriedade for alterado por alguma força externa (de uma forma diferente de chamar métodos no objeto), gerar eventos indicará ao desenvolvedor que o valor está mudando e foi alterado. Um bom exemplo é a propriedade Text de um controle de caixa de texto. Quando o usuário digita texto em um TextBox, o valor da propriedade muda automaticamente.

Portions © 2005, 2009 Microsoft Corporation. Todos os direitos reservados.

Reimpresso com permissão da Pearson Education, Inc. das Diretrizes de Design do Framework: convenções, linguagens e padrões para bibliotecas do .NET reutilizável, 2ª edição por Krzysztof Cwalina e Brad Abrams, publicado em 22 de outubro de 2008 por Addison-Wesley Professional como parte da série de desenvolvimento do Microsoft Windows.

Confira também