Destinazioni degli attributi (C++/CLI e C++/CX)
Gli specificatori di utilizzo degli attributi consentono di specificare le destinazioni degli attributi. Ogni attributo viene definito per essere applicato a determinati elementi del linguaggio. Ad esempio, un attributo potrebbe essere definito per essere applicato solo alle classi e agli struct. Nell'elenco seguente vengono mostrati i possibili elementi sintattici per cui può essere utilizzato un attributo personalizzato. È possibile utilizzare combinazioni di questi valori (tramite l'OR logico).
Per specificare la destinazione dell'attributo, passare uno o più enumeratori AttributeTargets a AttributeUsageAttribute durante la definizione dell'attributo.
Di seguito è riportato un elenco di destinazioni degli attributi valide:
All
(si applica a tutti i costrutti)using namespace System; [AttributeUsage(AttributeTargets::All)] ref class Attr : public Attribute {}; [assembly:Attr];
Assembly
(si applica a un assembly nel suo complesso)using namespace System; [AttributeUsage(AttributeTargets::Assembly)] ref class Attr : public Attribute {}; [assembly:Attr];
Module
(si applica a un modulo nel suo complesso)using namespace System; [AttributeUsage(AttributeTargets::Module)] ref class Attr : public Attribute {}; [module:Attr];
Class
using namespace System; [AttributeUsage(AttributeTargets::Class)] ref class Attr : public System::Attribute {}; [Attr] // same as [class:Attr] ref class MyClass {};
Struct
using namespace System; [AttributeUsage(AttributeTargets::Struct)] ref class Attr : public Attribute {}; [Attr] // same as [struct:Attr] value struct MyStruct{};
enum
using namespace System; [AttributeUsage(AttributeTargets::Enum)] ref class Attr : public Attribute {}; [Attr] // same as [enum:Attr] enum struct MyEnum{e, d};
Constructor
using namespace System; [AttributeUsage(AttributeTargets::Constructor)] ref class Attr : public Attribute {}; ref struct MyStruct{ [Attr] MyStruct(){} // same as [constructor:Attr] };
Method
using namespace System; [AttributeUsage(AttributeTargets::Method)] ref class Attr : public Attribute {}; ref struct MyStruct{ [Attr] void Test(){} // same as [method:Attr] };
Property
using namespace System; [AttributeUsage(AttributeTargets::Property)] ref class Attr : public Attribute {}; ref struct MyStruct{ [Attr] property int Test; // same as [property:Attr] };
Field
using namespace System; [AttributeUsage(AttributeTargets::Field)] ref class Attr : public Attribute {}; ref struct MyStruct{ [Attr] int Test; // same as [field:Attr] };
Event
using namespace System; [AttributeUsage(AttributeTargets::Event)] ref class Attr : public Attribute {}; delegate void ClickEventHandler(int, double); ref struct MyStruct{ [Attr] event ClickEventHandler^ OnClick; // same as [event:Attr] };
Interface
using namespace System; [AttributeUsage(AttributeTargets::Interface)] ref class Attr : public Attribute {}; [Attr] // same as [event:Attr] interface struct MyStruct{};
Parameter
using namespace System; [AttributeUsage(AttributeTargets::Parameter)] ref class Attr : public Attribute {}; ref struct MyStruct{ void Test([Attr] int i); void Test2([parameter:Attr] int i); };
Delegate
using namespace System; [AttributeUsage(AttributeTargets::Delegate)] ref class Attr : public Attribute {}; [Attr] delegate void Test(); [delegate:Attr] delegate void Test2();
ReturnValue
using namespace System; [AttributeUsage(AttributeTargets::ReturnValue)] ref class Attr : public Attribute {}; ref struct MyStruct { // Note required specifier [returnvalue:Attr] int Test() { return 0; } };
In genere, un attributo precede direttamente l'elemento del linguaggio a cui si applica. In alcuni casi, tuttavia, la posizione di un attributo non è sufficiente per determinare la relativa destinazione prevista. Si consideri questo esempio:
[Attr] int MyFn(double x)...
Da un punto di vista sintattico, non è possibile dire se l'attributo è progettato per essere applicato al metodo o al valore restituito del metodo (in questo caso, è impostato in modo predefinito sul metodo). In questi casi, è possibile utilizzare un identificatore di utilizzo degli attributi. Ad esempio, per fare in modo che l'attributo si applichi al valore restituito, utilizzare l'identificatore returnvalue
come riportato di seguito:
[returnvalue:Attr] int MyFn(double x)... // applies to return value
Gli identificatori di utilizzo degli attributi sono obbligatori nelle situazioni seguenti:
Per specificare un attributo a livello di modulo o di assembly.
Per specificare che un attributo viene applicato al valore restituito di un metodo e non al metodo:
[method:Attr] int MyFn(double x)... // Attr applies to method [returnvalue:Attr] int MyFn(double x)...// Attr applies to return value [Attr] int MyFn(double x)... // default: method
Per specificare che un attributo viene applicato alla funzione di accesso di una proprietà e non alla proprietà:
[method:MyAttr(123)] property int Property() [property:MyAttr(123)] property int Property() [MyAttr(123)] property int get_MyPropy() // default: property
Per specificare che un attributo viene applicato alla funzione di accesso di un evento e non all'evento:
delegate void MyDel(); ref struct X { [field:MyAttr(123)] event MyDel* MyEvent; //field [event:MyAttr(123)] event MyDel* MyEvent; //event [MyAttr(123)] event MyDel* MyEvent; // default: event }
Un identificatore di utilizzo degli attributi si applica solo all'attributo immediatamente successivo, cioè
[returnvalue:Attr1, Attr2]
è diverso da
[returnvalue:Attr1, returnvalue:Attr2]
Esempio
Descrizione
In questo esempio viene illustrato come specificare più destinazioni.
Codice
using namespace System;
[AttributeUsage(AttributeTargets::Class | AttributeTargets::Struct, AllowMultiple = true )]
ref struct Attr : public Attribute {
Attr(bool i){}
Attr(){}
};
[Attr]
ref class MyClass {};
[Attr]
[Attr(true)]
value struct MyStruct {};