Atributy v jazyce Visual Basic

Jazyk Visual Basic umožňuje programátoru určit modifikátory u deklarací, které představují informace o deklarovaných entitách. Například připojování metody třídy modifikátory Public, Protected, Friend, Protected Friendnebo Private určuje jeho přístupnost.

Kromě modifikátorů definovaných jazykem umožňuje Jazyk Visual Basic také programátorům vytvářet nové modifikátory označované jako atributy a používat je při deklarování nových entit. Tyto nové modifikátory, které jsou definovány prostřednictvím deklarace tříd atributů, jsou pak přiřazeny entitám prostřednictvím bloků atributů.

Poznámka. Atributy lze načíst za běhu prostřednictvím rozhraní API reflexe rozhraní .NET Framework. Tato rozhraní API jsou mimo rozsah této specifikace.

Například architektura může definovat Help atribut, který lze umístit na prvky programu, jako jsou třídy a metody, které poskytují mapování z prvků programu do dokumentace, jak ukazuje následující příklad:

<AttributeUsage(AttributeTargets.All)> _
Public Class HelpAttribute
    Inherits Attribute

    Public Sub New(urlValue As String)
        Me.UrlValue = urlValue
    End Sub

    Public Topic As String
    Private UrlValue As String

    Public ReadOnly Property Url() As String
        Get
            Return UrlValue
        End Get
    End Property
End Class

Příklad definuje třídu atributu s názvem , nebo Help pro krátkou, která má jeden poziční parametr (UrlValue) a jeden pojmenovaný argument (Topic).HelpAttribute

Následující příklad ukazuje několik použití atributu:

<Help("http://www.example.com/.../Class1.htm")> _
Public Class Class1
    <Help("http://www.example.com/.../Class1.htm", Topic:="F")> _
    Public Sub F()
    End Sub
End Class

Další příklad zkontroluje, jestli Class1Help atribut, a zapíše přidružené Topic a Url hodnoty, pokud je atribut přítomen.

Module Test
    Sub Main()
        Dim type As Type = GetType(Class1)
        Dim arr() As Object = _
            type.GetCustomAttributes(GetType(HelpAttribute), True)

        If arr.Length = 0 Then
            Console.WriteLine("Class1 has no Help attribute.")
        Else
            Dim ha As HelpAttribute = CType(arr(0), HelpAttribute)
            Console.WriteLine("Url = " & ha.Url & ", Topic = " & ha.Topic)
        End If
    End Sub
End Module

Třídy atributů

Třída atributu je ne generická třída, která je odvozena a System.Attribute není MustInherit. Třída atributu System.AttributeUsage může mít atribut, který deklaruje, co je atribut platný, zda jej lze použít vícekrát v deklaraci a zda je zděděna. Následující příklad definuje třídu atributů pojmenovanou SimpleAttribute , která se dá umístit do deklarací tříd a deklarací rozhraní:

<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Interface)> _
Public Class SimpleAttribute
    Inherits System.Attribute
End Class

Následující příklad ukazuje několik použití atributu Simple . Ačkoli je třída atributu pojmenována SimpleAttribute, použití tohoto atributu může vynechat příponu Attribute , a tím zkrátit název na Simple:

<Simple> Class Class1
End Class

<Simple> Interface Interface1
End Interface

Pokud atribut nemá System.AttributeUsagehodnotu , může být atribut umístěn do libovolného cíle (ekvivalentní AttributeTargets.All). Atribut System.AttributeUsage má inicializátor proměnné, který určuje, AllowMultiplezda lze zadaný atribut zadat více než jednou pro danou deklaraci. Pokud AllowMultiple je Trueatribut , je to třída atributu multiple-use a lze zadat více než jednou v deklaraci. Pokud AllowMultiple je False atribut atribut nebo není určen pro atribut, jedná se o třídu atributu s jedním použitím a lze ji zadat maximálně najednou v deklaraci.

Následující příklad definuje třídu atributu multiple-use s názvem AuthorAttribute:

<AttributeUsage(AttributeTargets.Class, AllowMultiple:=True)> _
Public Class AuthorAttribute
    Inherits System.Attribute

    Private _Value As String

    Public Sub New(value As String)
        Me._Value = value
    End Sub

    Public ReadOnly Property Value() As String
        Get
            Return _Value
        End Get
    End Property
End Class

Příklad ukazuje deklaraci třídy se dvěma použitími atributu Author :

<Author("Maria Hammond"), Author("Ramesh Meyyappan")> _
Class Class1
End Class

Atribut System.AttributeUsage má proměnnou veřejné instance, která určuje, Inheritedzda atribut, pokud je zadán základní typ, je také zděděna typy, které jsou odvozeny z tohoto základního typu. Inherited Pokud není inicializována proměnná veřejné instance, použije se výchozí hodnotaFalse. Vlastnosti a události nedědí atributy, i když metody definované vlastnostmi a událostmi. Rozhraní nedědí atributy.

Pokud je atribut s jedním použitím zděděný i zadaný pro odvozený typ, atribut zadaný u odvozeného typu přepíše zděděný atribut. Pokud je atribut multiple-use zděděný i zadaný pro odvozený typ, oba atributy jsou zadány na odvozený typ. Například:

<AttributeUsage(AttributeTargets.Class, AllowMultiple:=True, _
                Inherited:=True) > _
Class MultiUseAttribute
    Inherits System.Attribute

    Public Sub New(value As Boolean)
    End Sub
End Class

<AttributeUsage(AttributeTargets.Class, Inherited:=True)> _
Class SingleUseAttribute
    Inherits Attribute

    Public Sub New(value As Boolean)
    End Sub
End Class

<SingleUse(True), MultiUse(True)> Class Base
End Class

' Derived has three attributes defined on it: SingleUse(False),
' MultiUse(True) and MultiUse(False)
<SingleUse(False), MultiUse(False)> _
Class Derived
    Inherits Base
End Class

Poziční parametry atributu jsou definovány parametry veřejných konstruktorů třídy atributu. Poziční parametry musí být ByVal a nesmí být zadány ByRef. Proměnné a vlastnosti veřejné instance jsou definovány veřejnými vlastnostmi čtení a zápisu nebo proměnnými instance třídy atributu. Typy, které lze použít v pozičních parametrech a proměnných a vlastnostech veřejné instance, jsou omezeny na typy atributů. Typ je typ atributu, pokud se jedná o jeden z následujících typů:

  • Jakýkoli primitivní typ s výjimkou Date a Decimal.

  • Typ Object.

  • Typ System.Type.

  • Výčtový typ za předpokladu, že je a typy, ve kterých je vnořený (pokud existuje), mají Public přístupnost.

  • Jednorozměrné pole jednoho z předchozích typů v tomto seznamu.

Bloky atributů

Atributy jsou zadané v blocích atributů. Každý blok atributu je oddělený úhlovými závorkami ("<>") a v seznamu odděleném čárkami v bloku atributu nebo v několika blocích atributů lze zadat více atributů. Pořadí, ve kterém jsou zadané atributy, není významné. Například bloky <A, B>atributů , <B, A><A> <B> a <B> <A> jsou všechny ekvivalentní.

Attributes
    : AttributeBlock+
    ;

AttributeBlock
    : LineTerminator? '<' AttributeList LineTerminator? '>' LineTerminator?
    ;

AttributeList
    : Attribute ( Comma Attribute )*
    ;

Attribute
    : ( AttributeModifier ':' )? SimpleTypeName
    ( OpenParenthesis AttributeArguments? CloseParenthesis )?
    ;

AttributeModifier
    : 'Assembly' | 'Module'
    ;

Atribut nelze zadat pro druh deklarace, který nepodporuje, a atributy s jedním použitím nemusí být zadány více než jednou v bloku atributu. Následující příklad způsobuje chyby jak proto, že se pokusí použít HelpString v rozhraní Interface1 a více než jednou v deklaraci .Class1

<AttributeUsage(AttributeTargets.Class)> _
Public Class HelpStringAttribute
    Inherits System.Attribute

    Private InternalValue As String

    Public Sub New(value As String)
        Me.InternalValue = value
    End Sub

    Public ReadOnly Property Value() As String
        Get
            Return InternalValue
        End Get
    End Property
End Class

' Error: HelpString only applies to classes.
<HelpString("Description of Interface1")> _
Interface Interface1
    Sub Sub1()
End Interface

' Error: HelpString is single-use.
<HelpString("Description of Class1"), _
    HelpString("Another description of Class1")> _
Public Class Class1
End Class

Atribut se skládá z volitelného modifikátoru atributu, názvu atributu, volitelného seznamu pozičních argumentů a inicializátorů proměnných/vlastností. Pokud neexistují žádné parametry nebo inicializátory, mohou být závorky vynechány. Pokud má atribut modifikátor, musí být v bloku atributu v horní části zdrojového souboru.

Pokud zdrojový soubor obsahuje blok atributů v horní části souboru, který určuje atributy sestavení nebo modulu, které budou obsahovat zdrojový soubor, musí být každý atribut v bloku atributu předponou jak AssemblyModule modifikátorem, tak dvojtečka.

Názvy atributů

Název atributu určuje třídu atributu. Podle konvence jsou třídy atributů pojmenovány příponou Attribute. Použití atributu může obsahovat nebo vynechat tuto příponu. V důsledku toho je název třídy atributu, která odpovídá identifikátoru atributu, buď samotný identifikátor, nebo zřetězení kvalifikovaného identifikátoru a Attribute. Když kompilátor přeloží název atributu, připojí Attribute se k názvu a pokusí se vyhledat. Pokud se vyhledávání nezdaří, kompilátor zkusí vyhledávání bez přípony. Například použití třídy SimpleAttribute atributu může vynechat příponu Attribute , a tím zkrátit název na Simple:

<Simple> Class Class1
End Class

<Simple> Interface Interface1
End Interface

Výše uvedený příklad je sémanticky ekvivalentní následujícímu:

<SimpleAttribute> Class Class1
End Class

<SimpleAttribute> Interface Interface1
End Interface

Obecně se preferují atributy pojmenované s příponou Attribute . Následující příklad ukazuje dvě třídy atributů pojmenované T a T``Attribute.

<AttributeUsage(AttributeTargets.All)> _
Public Class T
    Inherits System.Attribute
End Class

<AttributeUsage(AttributeTargets.All)> _
Public Class TAttribute
    Inherits System.Attribute
End Class

' Refers to TAttribute.
<T> Class Class1 
End Class

' Refers to TAttribute.
<TAttribute> Class Class2 
End Class

Blok atributu <T> i blok <TAttribute> atributu odkazují na třídu atributů s názvem TAttribute. Nelze použít T jako atribut, dokud neodeberete deklaraci třídy TAttribute.

Argumenty atributů

Argumenty atributu mohou mít dvě formy: poziční argumenty a inicializátory proměnných instancí nebo vlastností. Všechny poziční argumenty atributu musí předcházet inicializátorům proměnné instance nebo vlastnosti. Poziční argument se skládá z konstantního výrazu, jednorozměrného výrazu pro vytvoření pole nebo výrazu GetType . Inicializátor proměnné instance nebo vlastnosti se skládá z identifikátoru, který může odpovídat klíčovým slovům, následovaný dvojtečku a rovnítkem a ukončený konstantním výrazem nebo výrazem GetType .

Při přiřazení atributu třídy T, seznamu Ppozičních argumentů a seznamu Ninicializátoru instance/vlastnosti určíte, zda jsou argumenty platné:

  1. Při kompilaci výrazu formuláře New T(P)postupujte podle kroků pro zpracování času kompilace . Výsledkem je chyba v době kompilace nebo určuje konstruktor T , který je nejužitčnější pro seznam argumentů.

  2. Pokud konstruktor určený v kroku 1 obsahuje parametry, které nejsou typy atributů nebo jsou v lokalitě deklarace nedostupné, dojde k chybě v době kompilace.

  3. Pro každou inicializátor Arg instance proměnné nebo vlastnosti , Nlet být Name identifikátor instance variable/property initializer Arg. Name musí identifikovat vlastnost, která neníShared zapisovatelná, Public proměnná instance nebo bez parametrů, u T které je typ atributu. Pokud T nemá takovou proměnnou instance nebo vlastnost, dojde k chybě v době kompilace.

Například:

<AttributeUsage(AttributeTargets.All)> _
Public Class GeneralAttribute
    Inherits Attribute

    Public Sub New(x As Integer)
    End Sub

    Public Sub New(x As Double)
    End Sub

    Public y As Type

    Public Property z As Integer
        Get
        End Get

        Set
        End Set
    End Property
End Class

' Calls the first constructor.
<General(10, z:=30, y:=GetType(Integer))> _
Class C1
End Class

' Calls the second constructor.
<General(10.5, z:=10)> _
Class C2
End Class

Parametry typu nelze použít kdekoli v argumentech atributu. Lze však použít vytvořené typy:

<AttributeUsage(AttributeTargets.All)> _
Class A 
   Inherits System.Attribute 

   Public Sub New(t As Type)
   End Sub 
End Class

Class List(Of T) 
    ' Error: attribute argument cannot use type parameter
    <A(GetType(T))> Dim t1 As T 

    ' OK: closed type
    <A(GetType(List(Of Integer)))> Dim y As Integer
End Class
AttributeArguments
    : AttributePositionalArgumentList
    | AttributePositionalArgumentList Comma VariablePropertyInitializerList
    | VariablePropertyInitializerList
    ;

AttributePositionalArgumentList
    : AttributeArgumentExpression? ( Comma AttributeArgumentExpression? )*
    ;

VariablePropertyInitializerList
    : VariablePropertyInitializer ( Comma VariablePropertyInitializer )*
    ;

VariablePropertyInitializer
    : IdentifierOrKeyword ColonEquals AttributeArgumentExpression
    ;

AttributeArgumentExpression
    : ConstantExpression
    | GetTypeExpression
    | ArrayExpression
    ;