Visual Basic의 특성

Visual Basic 언어를 사용하면 프로그래머가 선언할 엔터티에 대한 정보를 나타내는 선언에 대한 한정자를 지정할 수 있습니다. 예를 들어 클래스 메서드에 한정자Public, Protected, FriendProtected FriendPrivate 또는 해당 접근성을 지정합니다.

Visual Basic은 언어로 정의된 한정자 외에도 프로그래머가 특성이라는 새 한정자를 만들고 새 엔터티를 선언할 때 사용할 수 있도록 합니다. 특성 클래스 선언을 통해 정의된 이러한 새 한정자는 특성 블록을 통해 엔터티에 할당됩니다.

메모. .NET Framework의 리플렉션 API를 통해 런타임에 특성을 검색할 수 있습니다. 이러한 API는 이 사양의 범위를 벗어습니다.

예를 들어 프레임워크는 다음 예제와 같이 프로그램 요소에서 설명서로 매핑을 제공하기 위해 클래스 및 메서드와 같은 프로그램 요소에 배치할 수 있는 특성을 정의 Help 할 수 있습니다.

<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

이 예제에서는 위치 매개 변수()와 명명HelpAttribute된 인수(UrlValue)가 하나 있는 특성 클래스를Topic 정의합니다Help.

다음 예제에서는 특성의 몇 가지 용도를 보여 있습니다.

<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

다음 예제에서는 특성이 Help 있는지 Class1 확인하고 특성이 있는 경우 연결된 Topic 값과 Url 값을 기록합니다.

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

특성 클래스

특성 클래스는 파생 System.Attribute 되고 파생되지 않는 제네릭이 아닌 MustInherit클래스입니다. 특성 클래스에는 System.AttributeUsage 특성이 유효한 항목, 선언에서 여러 번 사용될 수 있는지 여부 및 상속 여부를 선언하는 특성이 있을 수 있습니다. 다음 예제에서는 클래스 선언 및 인터페이스 선언에 배치할 수 있는 명명된 SimpleAttribute 특성 클래스를 정의합니다.

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

다음 예제에서는 특성의 Simple 몇 가지 사용을 보여줍니다. 특성 클래스의 이름은 지정 SimpleAttribute되지만 이 특성의 사용은 접미사를 생략 Attribute 하여 이름을 Simple다음과 같이 줄입니다.

<Simple> Class Class1
End Class

<Simple> Interface Interface1
End Interface

특성에 없는 System.AttributeUsage경우 특성은 모든 대상(해당 AttributeTargets.All)에 배치할 수 있습니다. 특성에는 System.AttributeUsage 지정된 선언에 대해 지정된 특성을 두 번 이상 지정할 수 있는지 여부를 지정하는 변수 이니셜라이저 AllowMultiple가 있습니다. 특성의 True경우 AllowMultiple다중 사용 특성 클래스이며 선언에서 두 번 이상 지정할 수 있습니다. 특성이 False 특성에 대해 지정되지 않거나 지정되지 않은 경우 AllowMultiple단일 사용 특성 클래스이며 선언에서 최대 한 번 지정할 수 있습니다.

다음 예제에서는 명명 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

이 예제에서는 두 가지 특성을 사용하는 클래스 선언을 Author 보여줍니다.

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

특성에는 System.AttributeUsage 기본 형식에 지정된 특성이 이 기본 형식에서 파생된 형식에 의해 상속되는지 여부를 지정하는 공용 인스턴스 변수 Inherited가 있습니다. 공용 인스턴스 변수가 Inherited 초기화되지 않은 경우 기본값 False 이 사용됩니다. 속성 및 이벤트로 정의된 메서드는 특성을 상속하지 않지만 속성과 이벤트는 특성을 상속하지 않습니다. 인터페이스는 특성을 상속하지 않습니다.

단일 사용 특성이 모두 상속되고 파생 형식에 지정된 경우 파생 형식에 지정된 특성이 상속된 특성을 재정의합니다. 다중 사용 특성이 파생 형식에 상속되고 지정된 경우 두 특성이 모두 파생 형식에 지정됩니다. 다음은 그 예입니다.

<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

특성의 위치 매개 변수는 특성 클래스의 공용 생성자의 매개 변수에 의해 정의됩니다. 위치 매개 변수는 지정해야 ByVal 하며 지정할 ByRef수 없습니다. 공용 인스턴스 변수 및 속성은 특성 클래스의 공용 읽기-쓰기 속성 또는 인스턴스 변수에 의해 정의됩니다. 위치 매개 변수 및 공용 인스턴스 변수 및 속성에 사용할 수 있는 형식은 특성 형식으로 제한됩니다. 형식은 다음 중 하나인 경우 특성 형식입니다.

  • 및 을 제외한 DateDecimal모든 기본 형식

  • Object 형식입니다.

  • System.Type 형식입니다.

  • 열거형 형식이며 중첩된 형식(있는 경우)에 접근성이 Public 있는 경우

  • 이 목록에 있는 이전 형식 중 하나의 1차원 배열입니다.

특성 블록

특성은 특성 블록에 지정됩니다. 각 특성 블록은 꺾쇠 괄호("<>")로 구분되며, 특성 블록 내의 쉼표로 구분된 목록이나 여러 특성 블록에서 여러 특성을 지정할 수 있습니다. 특성이 지정된 순서는 중요하지 않습니다. 예를 들어 특성 <A, B><B, A><A> <B><B> <A> 블록은 모두 동일합니다.

Attributes
    : AttributeBlock+
    ;

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

AttributeList
    : Attribute ( Comma Attribute )*
    ;

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

AttributeModifier
    : 'Assembly' | 'Module'
    ;

지원하지 않는 선언의 종류에 특성을 지정하지 않을 수 있으며, 단일 사용 특성은 특성 블록에서 두 번 이상 지정되지 않을 수 있습니다. 아래 예제에서는 인터페이스 Interface1 에서 사용하려고 시도하고 선언Class1에서 두 번 이상 사용 HelpString 하려고 하므로 오류가 발생합니다.

<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

특성은 선택적 특성 한정자, 특성 이름, 위치 인수의 선택적 목록 및 변수/속성 이니셜라이저로 구성됩니다. 매개 변수 또는 이니셜라이저가 없으면 괄호를 생략할 수 있습니다. 특성에 한정자가 있는 경우 원본 파일의 맨 위에 있는 특성 블록에 있어야 합니다.

원본 파일에 원본 파일을 포함할 어셈블리 또는 모듈의 특성을 지정하는 파일 맨 위에 특성 블록이 있는 경우 특성 블록의 각 특성 앞에는 또는 한정자와 콜론이 모두 AssemblyModule 접두사로 지정되어야 합니다.

특성 이름

특성의 이름은 특성 클래스를 지정합니다. 규칙에 따라 특성 클래스의 이름은 접미사 Attribute로 지정됩니다. 특성의 사용은 이 접미사를 포함하거나 생략할 수 있습니다. 따라서 특성 식별자에 해당하는 특성 클래스의 이름은 식별자 자체 또는 정규화된 식별자와 Attribute의 연결입니다. 컴파일러가 특성 이름을 확인하면 이름에 추가하고 Attribute 조회를 시도합니다. 해당 조회가 실패하면 컴파일러는 접미사 없이 조회를 시도합니다. 예를 들어 특성 클래스 SimpleAttribute 를 사용하여 접미사를 생략 Attribute 하여 이름을 Simple다음과 같이 줄일 수 있습니다.

<Simple> Class Class1
End Class

<Simple> Interface Interface1
End Interface

위의 예제는 의미상 다음과 같습니다.

<SimpleAttribute> Class Class1
End Class

<SimpleAttribute> Interface Interface1
End Interface

일반적으로 접미사를 Attribute 사용하여 명명된 특성이 선호됩니다. 다음 예제에서는 명명 T 된 두 개의 특성 클래스와 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

특성 블록과 특성 블록 <T><TAttribute> 은 모두 명명 TAttribute된 특성 클래스를 참조합니다. 클래스TAttribute에 대한 선언을 제거할 때까지 특성으로 사용할 T 수 없습니다.

특성 인수

특성에 대한 인수는 위치 인수인스턴스 변수/속성 이니셜라이저의 두 가지 형식을 사용할 수 있습니다. 특성에 대한 모든 위치 인수는 인스턴스 변수/속성 이니셜라이저 앞에 있어야 합니다. 위치 인수는 상수 식, 1차원 배열 생성 식 또는 GetType 식으로 구성됩니다. 인스턴스 변수/속성 이니셜라이저는 키워드와 일치할 수 있는 식별자로 구성되며, 콜론과 등호가 뒤따르고 상수 식이나 GetType 식으로 종료됩니다.

특성 클래스T, 위치 인수 목록 및 인스턴스 변수/속성 이니셜라이저 목록이 PN있는 특성을 지정하면 다음 단계에서 인수가 유효한지 여부를 결정합니다.

  1. 양식 New T(P)의 식을 컴파일하기 위한 컴파일 시간 처리 단계를 따릅니다. 이로 인해 컴파일 시간 오류가 발생하거나 인수 목록에 가장 적합한 생성자를 T 결정합니다.

  2. 1단계에서 결정된 생성자에 특성 형식이 아니거나 선언 사이트에서 액세스할 수 없는 매개 변수가 있는 경우 컴파일 시간 오류가 발생합니다.

  3. 각 인스턴스 변수/속성 이니셜라이저 ArgNName 대해 인스턴스 변수/속성 이니셜라이저Arg의 식별자가 됩니다. Name 는 형식이 특성 형식인 비Shared, 쓰기 가능, Public 인스턴스 변수 또는 매개 변수 없는 속성을 T 식별해야 합니다. 이러한 인스턴스 변수 또는 속성이 없으면 T 컴파일 시간 오류가 발생합니다.

다음은 그 예입니다.

<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

특성 인수의 어디에서도 형식 매개 변수를 사용할 수 없습니다. 그러나 생성된 형식을 사용할 수 있습니다.

<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
    ;