Attributi

Gli attributi offrono un metodo efficace per l'associazione di metadati o informazioni dichiarative con il codice (assembly, tipi, metodi, proprietà e così via). Dopo aver associato un attributo a un'entità di programma, in fase di esecuzione è possibile eseguire una query su tale attributo usando una tecnica denominata reflection.

Di seguito sono riportate le proprietà degli attributi:

  • Gli attributi aggiungono metadati al programma. I metadati sono informazioni relative ai tipi definiti in un programma. Tutti gli assembly .NET contengono un set specificato di metadati che descrive i tipi e membri dei tipi definiti nell'assembly. È possibile aggiungere attributi personalizzati per specificare altre informazioni eventualmente necessarie.
  • È possibile applicare uno o più attributi a interi assembly, moduli o elementi di programma di minori dimensioni, ad esempio classi e proprietà.
  • Gli attributi possono accettare argomenti nello stesso modo dei metodi e delle proprietà.
  • Il programma può esaminare i propri metadati oppure i metadati di un altro programma tramite reflection.

La reflection specifica oggetti di tipo Type che descrivono assembly, moduli e tipi. È possibile usare la reflection per creare in modo dinamico un'istanza di un tipo, associare il tipo a un oggetto esistente oppure ottenere il tipo da un oggetto esistente e richiamarne i metodi o accedere ai relativi campi e proprietà. Se usi attributi nel codice, la reflection consente di accedervi. Per altre informazioni, vedere Attributi.

Di seguito è riportato un esempio semplice di reflection che usa il metodo GetType() ereditato da tutti i tipi dalla classe di base Object per ottenere il tipo di una variabile:

Nota

Assicurati di aggiungere using System; e using System.Reflection; nella parte superiore del file .cs.

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

L'output è: System.Int32.

L'esempio seguente usa la reflection per ottenere il nome completo dell'assembly caricato.

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

L'output è simile al seguente: System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.

Nota

Le parole chiave di C# protected e internal non hanno significato nel linguaggio intermedio (IL) e non sono usate nelle API di reflection. I termini corrispondenti in IL sono Famiglia e Assembly. Per identificare un metodo internal tramite reflection, usare la proprietà IsAssembly. Per identificare un metodo protected internal, usare IsFamilyOrAssembly.

Usare gli attributi

È possibile usare attributi in quasi tutte le dichiarazioni, anche se la validità di un attributo specifico può essere limitata ad alcuni tipi di dichiarazione. Per specificare un attributo in C# inserisci il nome dell'attributo racchiuso tra parentesi quadre ([]) sopra la dichiarazione dell'entità a cui è applicato.

Nell'esempio seguente l'attributo SerializableAttribute viene usato per applicare una caratteristica specifica a una classe:

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

Un metodo con l'attributo DllImportAttribute è dichiarato come nell'esempio seguente:

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

In una dichiarazione è possibile inserire più attributi, come illustrato nell'esempio seguente:

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

Alcuni attributi possono essere specificati più volte per una stessa entità. Un esempio di attributo multiuso è ConditionalAttribute:

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

Nota

Per convenzione tutti i nomi di attributo terminano con la parola "Attribute", in modo che sia possibile distinguerli da altri elementi delle librerie .NET. Tuttavia, quando gli attributi vengono usati nel codice, non è necessario specificare il suffisso Attribute. Ad esempio [DllImport] è equivalente a [DllImportAttribute], mentre DllImportAttribute è il nome effettivo dell'attributo nella libreria di classi .NET.

Parametri degli attributi

Diversi attributi dispongono di parametri, che possono essere posizionali, senza nome o denominati. I parametri posizionali devono essere specificati in un determinato ordine e non possono essere omessi. I parametri denominati sono facoltativi e possono essere specificati in qualsiasi ordine. I parametri posizionali vengono specificati per primi. I tre attributi seguenti, ad esempio, sono equivalenti:

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

Il primo parametro, ovvero il nome della DLL, è posizionale ed è sempre specificato per primo. Gli altri parametri sono denominati. In questo caso, entrambi i parametri denominati sono impostati automaticamente su false e possono quindi essere omessi. I parametri posizionali corrispondono ai parametri del costruttore dell'attributo. I parametri denominati o facoltativi corrispondono a proprietà o campi dell'attributo. Per informazioni sui valori predefiniti dei parametri, fare riferimento alla documentazione di ciascun attributo.

Per altre informazioni sui tipi di parametro consentiti, vedi la sezione Attributi della specifica del linguaggio C#

Destinazioni degli attributi

La destinazione di un attributo è l'entità a cui tale attributo viene applicato. Un attributo, ad esempio, può essere applicato a una classe, a un metodo particolare o a un intero assembly. Per impostazione predefinita, un attributo viene applicato all'elemento che lo segue. È tuttavia possibile identificare in modo esplicito, ad esempio, se un attributo viene applicato a un metodo, al relativo parametro o al relativo valore restituito.

Per identificare in modo esplicito la destinazione di un attributo, usare la sintassi seguente:

[target : attribute-list]

Nella tabella seguente sono elencati i possibili valori di target.

Valore target Si applica a
assembly Intero assembly
module Modulo di assembly corrente
field Campo in una classe o uno struct
event Evento
method Metodo o funzioni di accesso alle proprietà get e set
param Parametri del metodo o parametri della funzione di accesso alla proprietà set
property Proprietà
return Valore restituito di un metodo, un indicizzatore di proprietà o una funzione di accesso alla proprietà get
type Struct, classe, interfaccia, enumeratore o delegato

È necessario specificare il valore di destinazione field per applicare un attributo al campo sottostante creato per una proprietà implementata automaticamente.

Nell'esempio seguente viene illustrato come applicare attributi ad assembly e moduli. Per altre informazioni, vedere Attributi comuni (C#).

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

Nell'esempio seguente viene illustrato come applicare gli attributi a metodi, parametri di metodo e valori restituiti dal metodo in 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; }

Nota

Indipendentemente dalle destinazioni in cui l'oggetto ValidatedContract è definito come valido, è necessario specificare la destinazione return, anche se ValidatedContract viene definito in modo da essere valido solo per i valori restituiti. In altre parole, il compilatore non usa le informazioni AttributeUsage per risolvere le destinazioni degli attributi ambigue. Per altre informazioni, vedi AttributeUsage.

Usi comuni degli attributi

Di seguito vengono elencati alcuni degli usi comuni degli attributi nel codice:

  • Contrassegno dei metodi mediante l'attributo WebMethod nei servizi Web per indicare che è possibile chiamare il metodo tramite il protocollo SOAP. Per ulteriori informazioni, vedere WebMethodAttribute.
  • Descrizione della procedura di marshalling dei parametri del metodo durante l'interazione con il codice nativo. Per ulteriori informazioni, vedere MarshalAsAttribute.
  • Descrizione delle proprietà COM per classi, metodi e interfacce.
  • Chiamata al codice non gestito che usa la classe DllImportAttribute.
  • Descrizione dell'assembly con indicazione di titolo, versione, descrizione o marchio.
  • Descrizione dei membri della classe da serializzare per la persistenza.
  • Descrizione della procedura di mapping tra membri di una classe e nodi XML per la serializzazione XML.
  • Descrivere i requisiti di sicurezza per i metodi.
  • Definizione delle caratteristiche usate per garantire la sicurezza.
  • Controllo delle ottimizzazioni tramite il compilatore JIT (Just-In-Time), in modo da garantire un semplice debug del codice.
  • Recupero di informazioni relative al chiamante di un metodo.

Panoramica della reflection

La reflection è utile nelle situazioni seguenti:

Per altre informazioni: