C # - Attributi
Un attributeè un tag dichiarativo che viene utilizzato per trasmettere informazioni al runtime sui comportamenti di vari elementi come classi, metodi, strutture, enumeratori, assembly ecc. nel programma. È possibile aggiungere informazioni dichiarative a un programma utilizzando un attributo. Un tag dichiarativo è rappresentato da parentesi quadre ([]) poste sopra l'elemento per cui è utilizzato.
Gli attributi vengono utilizzati per aggiungere metadati, come istruzioni del compilatore e altre informazioni come commenti, descrizione, metodi e classi a un programma. .Net Framework fornisce due tipi di attributi: gli attributi predefiniti e gli attributi personalizzati .
Specifica di un attributo
La sintassi per specificare un attributo è la seguente:
[attribute(positional_parameters, name_parameter = value, ...)]
element
Il nome dell'attributo e i suoi valori sono specificati all'interno delle parentesi quadre, prima dell'elemento a cui viene applicato l'attributo. I parametri posizionali specificano le informazioni essenziali ei parametri del nome specificano le informazioni facoltative.
Attributi predefiniti
.Net Framework fornisce tre attributi predefiniti:
- AttributeUsage
- Conditional
- Obsolete
AttributeUsage
L'attributo predefinito AttributeUsagedescrive come utilizzare una classe di attributi personalizzati. Specifica i tipi di elementi a cui può essere applicato l'attributo.
La sintassi per specificare questo attributo è la seguente:
[AttributeUsage (
validon,
AllowMultiple = allowmultiple,
Inherited = inherited
)]
Dove,
Il parametro validon specifica gli elementi del linguaggio su cui può essere posizionato l'attributo. È una combinazione del valore di un enumeratore AttributeTargets . Il valore predefinito è AttributeTargets.All .
Il parametro allowmultiple (facoltativo) fornisce il valore per la proprietà AllowMultiple di questo attributo, un valore booleano. Se questo è vero, l'attributo è multiuso. L'impostazione predefinita è false (monouso).
Il parametro inherited (facoltativo) fornisce un valore per la proprietà Inherited di questo attributo, un valore booleano. Se è vero, l'attributo viene ereditato dalle classi derivate. Il valore predefinito è false (non ereditato).
Per esempio,
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
Condizionale
Questo attributo predefinito contrassegna un metodo condizionale la cui esecuzione dipende da un identificatore di pre-elaborazione specificato.
Provoca la compilazione condizionale delle chiamate al metodo, a seconda del valore specificato come Debug o Trace. Ad esempio, visualizza i valori delle variabili durante il debug di un codice.
La sintassi per specificare questo attributo è la seguente:
[Conditional(
conditionalSymbol
)]
Per esempio,
[Conditional("DEBUG")]
Il seguente esempio dimostra l'attributo -
#define DEBUG
using System;
using System.Diagnostics;
public class Myclass {
[Conditional("DEBUG")]
public static void Message(string msg) {
Console.WriteLine(msg);
}
}
class Test {
static void function1() {
Myclass.Message("In Function 1.");
function2();
}
static void function2() {
Myclass.Message("In Function 2.");
}
public static void Main() {
Myclass.Message("In Main function.");
function1();
Console.ReadKey();
}
}
Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:
In Main function
In Function 1
In Function 2
Obsoleto
Questo attributo predefinito contrassegna un'entità del programma che non deve essere utilizzata. Consente di informare il compilatore di scartare un particolare elemento di destinazione. Ad esempio, quando un nuovo metodo viene utilizzato in una classe e se si desidera ancora conservare il vecchio metodo nella classe, è possibile contrassegnarlo come obsoleto visualizzando un messaggio, il nuovo metodo dovrebbe essere utilizzato, invece del vecchio metodo.
La sintassi per specificare questo attributo è la seguente:
[Obsolete (
message
)]
[Obsolete (
message,
iserror
)]
Dove,
Il messaggio del parametro è una stringa che descrive il motivo per cui l'elemento è obsoleto e cosa usare invece.
Il parametro iserror , è un valore booleano. Se il suo valore è vero, il compilatore dovrebbe considerare l'uso dell'elemento come un errore. Il valore predefinito è false (il compilatore genera un avviso).
Il seguente programma lo dimostra:
using System;
public class MyClass {
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod() {
Console.WriteLine("It is the old method");
}
static void NewMethod() {
Console.WriteLine("It is the new method");
}
public static void Main() {
OldMethod();
}
}
Quando si tenta di compilare il programma, il compilatore fornisce un messaggio di errore che indica:
Don't use OldMethod, use NewMethod instead
Creazione di attributi personalizzati
.Net Framework consente la creazione di attributi personalizzati che possono essere utilizzati per memorizzare informazioni dichiarative e possono essere recuperati in fase di esecuzione. Queste informazioni possono essere correlate a qualsiasi elemento target a seconda dei criteri di progettazione e delle esigenze dell'applicazione.
La creazione e l'utilizzo di attributi personalizzati comportano quattro passaggi:
- Dichiarazione di un attributo personalizzato
- Costruire l'attributo personalizzato
- Applicare l'attributo personalizzato a un elemento del programma di destinazione
- Accesso agli attributi tramite la riflessione
L'ultimo passaggio prevede la scrittura di un semplice programma per leggere i metadati per trovare varie notazioni. I metadati sono dati su dati o informazioni utilizzati per descrivere altri dati. Questo programma dovrebbe utilizzare le riflessioni per accedere agli attributi in fase di esecuzione. Ne parleremo nel prossimo capitolo.
Dichiarazione di un attributo personalizzato
Un nuovo attributo personalizzato dovrebbe è derivato da System.Attributeclasse. Per esempio,
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
Nel codice precedente, abbiamo dichiarato un attributo personalizzato denominato DeBugInfo .
Costruire l'attributo personalizzato
Costruiamo un attributo personalizzato denominato DeBugInfo , che memorizza le informazioni ottenute eseguendo il debug di qualsiasi programma. Lascia che memorizzi le seguenti informazioni:
- Il numero di codice del bug
- Nome dello sviluppatore che ha identificato il bug
- Data dell'ultima revisione del codice
- Un messaggio di stringa per memorizzare i commenti dello sviluppatore
La classe DeBugInfo ha tre proprietà private per archiviare le prime tre informazioni e una proprietà pubblica per archiviare il messaggio. Quindi il numero di bug, il nome dello sviluppatore e la data di revisione sono i parametri posizionali della classe DeBugInfo e il messaggio è un parametro facoltativo o denominato.
Ogni attributo deve avere almeno un costruttore. I parametri posizionali dovrebbero essere passati attraverso il costruttore. Il codice seguente mostra la classe DeBugInfo -
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute {
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d) {
this.bugNo = bg;
this.developer = dev;
this.lastReview = d;
}
public int BugNo {
get {
return bugNo;
}
}
public string Developer {
get {
return developer;
}
}
public string LastReview {
get {
return lastReview;
}
}
public string Message {
get {
return message;
}
set {
message = value;
}
}
}
Applicazione dell'attributo personalizzato
L'attributo viene applicato posizionandolo immediatamente prima del suo obiettivo -
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
//member variables
protected double length;
protected double width;
public Rectangle(double l, double w) {
length = l;
width = w;
}
[DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
public double GetArea() {
return length * width;
}
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
Nel prossimo capitolo, recupereremo le informazioni sugli attributi utilizzando un oggetto della classe Reflection.