Partilhar via


Atributos

Os atributos fornecem um método poderoso de associar metadados, ou informações declarativas, com código (assemblies, tipos, métodos, propriedades e assim por diante). Depois que um atributo é associado a uma entidade de programa, o atributo pode ser consultado em tempo de execução usando uma técnica chamada reflection.

Os atributos têm as seguintes propriedades:

  • Os atributos adicionam metadados ao seu programa. Metadados é a informação sobre os tipos definidos em um programa. Todos os assemblies .NET contêm um conjunto especificado de metadados que descreve os tipos e membros de tipo definidos no assembly. Você pode adicionar atributos personalizados para especificar quaisquer informações adicionais necessárias.
  • Você pode aplicar um ou mais atributos a assemblies inteiros, módulos ou elementos de programa menores, como classes e propriedades.
  • Os atributos podem aceitar argumentos da mesma forma que métodos e propriedades.
  • Seu programa pode examinar seus próprios metadados ou os metadados em outros programas usando reflexão.

O de reflexão fornece objetos (do tipo Type) que descrevem assemblies, módulos e tipos. Você pode usar a reflexão para criar dinamicamente uma instância de um tipo, vincular o tipo a um objeto existente ou obter o tipo de um objeto existente e invocar seus métodos ou acessar seus campos e propriedades. Se você estiver usando atributos em seu código, a reflexão permitirá que você os acesse. Para obter mais informações, consulte Atributos.

Aqui está um exemplo simples de reflexão usando o método GetType() - herdado por todos os tipos da classe base Object - para obter o tipo de uma variável:

Observação

Certifique-se de adicionar using System; e using System.Reflection; na parte superior do arquivo .cs.

// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);

A saída é: System.Int32.

O exemplo a seguir usa reflection para obter o nome completo do assembly carregado.

// Using Reflection to get information of an Assembly:
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);

A saída é algo como: System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.

Observação

As palavras-chave C# protected e internal não têm significado na linguagem intermediária (IL) e não são usadas nas APIs de reflexão. Os termos correspondentes em IL são Family e Assembly. Para identificar um método internal usando reflexão, use a propriedade IsAssembly. Para identificar um método protected internal, use o IsFamilyOrAssembly.

Usando atributos

Os atributos podem ser colocados em quase todas as declarações, embora um atributo específico possa restringir os tipos de declarações nas quais é válido. Em C#, você especifica um atributo colocando o nome do atributo entre colchetes ([]) acima da declaração da entidade à qual ele se aplica.

Neste exemplo, o atributo SerializableAttribute é usado para aplicar uma característica específica a uma classe:

[Serializable]
public class SampleClass
{
    // Objects of this type can be serialized.
}

Um método com o atributo DllImportAttribute é declarado como o exemplo a seguir:

[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();

Mais de um atributo pode ser colocado em uma declaração, como mostra o exemplo a seguir:

void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }

Alguns atributos podem ser especificados mais de uma vez para uma determinada entidade. Um exemplo desse atributo multiuso é ConditionalAttribute:

[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
    // ...
}

Observação

Por convenção, todos os nomes de atributos terminam com a palavra "Atributo" para distingui-los de outros itens nas bibliotecas .NET. No entanto, você não precisa especificar o sufixo de atributo ao usar atributos no código. Por exemplo, [DllImport] é equivalente a [DllImportAttribute], mas DllImportAttribute é o nome real do atributo na Biblioteca de Classes do .NET.

Parâmetros de atributo

Muitos atributos têm parâmetros, que podem ser posicionais, sem nome ou nomeados. Quaisquer parâmetros posicionais devem ser especificados em uma determinada ordem e não podem ser omitidos. Os parâmetros nomeados são opcionais e podem ser especificados em qualquer ordem. Os parâmetros posicionais são especificados primeiro. Por exemplo, estes três atributos são equivalentes:

[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]

O primeiro parâmetro, o nome da DLL, é posicional e sempre vem em primeiro lugar; os outros são nomeados. Nesse caso, ambos os parâmetros nomeados têm como valor padrão false, por isso podem ser omitidos. Os parâmetros posicionais correspondem aos parâmetros do construtor do atributo. Os parâmetros nomeados ou opcionais correspondem às propriedades ou campos do atributo. Consulte a documentação do atributo individual para obter informações sobre valores de parâmetros padrão.

Para obter mais informações sobre os tipos de parâmetros permitidos, consulte a seção Atributos da especificação da linguagem C# .

Destinos de atributos

O destino do de um atributo é a entidade à qual o atributo se aplica. Por exemplo, um atributo pode se aplicar a uma classe, um método específico ou um assembly inteiro. Por padrão, um atributo se aplica ao elemento que o segue. Mas você também pode identificar explicitamente, por exemplo, se um atributo é aplicado a um método, ou ao seu parâmetro, ou ao seu valor de retorno.

Para identificar explicitamente um destino de atributo, use a seguinte sintaxe:

[target : attribute-list]

A lista de possíveis valores de target é mostrada na tabela a seguir.

Valor alvo Aplica-se a
assembly Montagem completa
module Módulo de montagem atual
field Campo em uma classe ou uma estrutura
event Evento
method Método ou acessores de propriedade get e set
param Parâmetros do método ou parâmetros do acessador de propriedade set
property Propriedade
return Valor de retorno de um método, indexador de propriedade ou acessador de propriedade get
type Estrutura, classe, interface, enumeração ou delegado

Você especificaria o valor de destino field para aplicar um atributo ao campo de suporte criado para uma propriedade implementada automaticamente.

O exemplo a seguir mostra como aplicar atributos a assemblies e módulos. Para obter mais informações, consulte Common Attributes (C#).

using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]

O exemplo a seguir mostra como aplicar atributos a métodos, parâmetros de método e valores de retorno de método em C#.

// default: applies to method
[ValidatedContract]
int Method1() { return 0; }

// applies to method
[method: ValidatedContract]
int Method2() { return 0; }

// applies to parameter
int Method3([ValidatedContract] string contract) { return 0; }

// applies to return value
[return: ValidatedContract]
int Method4() { return 0; }

Observação

Independentemente dos destinos em que o ValidatedContract é definido como válido, o destino return tem de ser especificado, mesmo que ValidatedContract tenham sido definidos para se aplicarem apenas aos valores de retorno. Em outras palavras, o compilador não usará a informação de AttributeUsage para resolver alvos de atributos ambíguos. Para obter mais informações, consulte AttributeUsage.

Usos comuns para atributos

A lista a seguir inclui alguns dos usos comuns de atributos no código:

  • Marcando métodos usando o atributo WebMethod em serviços Web para indicar que o método deve ser chamável sobre o protocolo SOAP. Para obter mais informações, consulte WebMethodAttribute.
  • Descrevendo como organizar parâmetros de método ao interoperar com código nativo. Para obter mais informações, consulte MarshalAsAttribute.
  • Descrevendo as propriedades COM para classes, métodos e interfaces.
  • Chamando código não gerenciado usando a classe DllImportAttribute.
  • Descrevendo sua montagem em termos de título, versão, descrição ou marca registrada.
  • Descrever o processo de determinar quais membros de uma classe devem ser serializados para persistência.
  • Descrever como mapear entre membros de classe e elementos XML para serialização XML.
  • Descrever os requisitos de segurança para os métodos.
  • Especificação das características utilizadas para reforçar a segurança.
  • Controlar as otimizações pelo compilador just-in-time (JIT) para que o código permaneça fácil de depurar.
  • Obter informações sobre o chamador de um método.

Visão geral da reflexão

A reflexão é útil nas seguintes situações:

Para mais informações: