Típusok a Visual Basicben

A Visual Basic két alapvető típusa az értéktípusok és a referenciatípusok. A primitív típusok (a sztringek kivételével), az enumerálások és a struktúrák értéktípusok. Az osztályok, sztringek, standard modulok, interfészek, tömbök és meghatalmazottak referenciatípusok.

Minden típushoz tartozik egy alapértelmezett érték, amely az inicializáláskor az adott típusú változókhoz rendelt érték.

TypeName
    : ArrayTypeName
    | NonArrayTypeName
    ;

NonArrayTypeName
    : SimpleTypeName
    | NullableTypeName
    ;

SimpleTypeName
    : QualifiedTypeName
    | BuiltInTypeName
    ;

QualifiedTypeName
    : Identifier TypeArguments? (Period IdentifierOrKeyword TypeArguments?)*
    | 'Global' Period IdentifierOrKeyword TypeArguments?
      (Period IdentifierOrKeyword TypeArguments?)*
    ;

TypeArguments
    : OpenParenthesis 'Of' TypeArgumentList CloseParenthesis
    ;

TypeArgumentList
    : TypeName ( Comma TypeName )*
    ;

BuiltInTypeName
    : 'Object'
    | PrimitiveTypeName
    ;

TypeModifier
    : AccessModifier
    | 'Shadows'
    ;

IdentifierModifiers
    : NullableNameModifier? ArrayNameModifier?
    ;

Értéktípusok és referenciatípusok

Bár az értéktípusok és a referenciatípusok hasonlóak lehetnek a deklaráció szintaxisa és használata szempontjából, szemantikájaik eltérőek.

A referenciatípusok a futásidejű halomon vannak tárolva; csak az adott tárterületre mutató hivatkozással érhetők el. Mivel a hivatkozástípusok mindig hivatkozásokkal érhetők el, élettartamukat a .NET-keretrendszer felügyeli. A rendszer nyomon követi az adott példányra mutató függőben lévő hivatkozásokat, és a példány csak akkor lesz megsemmisítve, ha már nincs több hivatkozás. A referenciatípus változója egy ilyen típusú értékre, egy származtatottabb típusú értékre vagy null értékre mutató hivatkozást tartalmaz. A null érték semmire nem utal; null értékkel semmit sem lehet tenni, csak hozzárendelni. Egy referenciatípusú változóhoz való hozzárendelés a hivatkozás másolatát hozza létre a hivatkozott érték másolata helyett. Hivatkozási típusú változó esetén az alapértelmezett érték null érték.

Az értéktípusok közvetlenül a veremen vannak tárolva, tömbön belül vagy egy másik típuson belül; a tárterületük csak közvetlenül érhető el. Mivel az értéktípusok közvetlenül a változókon belül vannak tárolva, élettartamukat az őket tartalmazó változó élettartama határozza meg. Ha az értéktípus-példányt tartalmazó hely megsemmisül, az értéktípus-példány is megsemmisül. Az értéktípusok mindig közvetlenül érhetők el; nem hozható létre értéktípusra mutató hivatkozás. Az ilyen hivatkozások tiltása lehetetlenné teszi, hogy egy megsemmisített értékosztálypéldányra hivatkozzon. Mivel az értéktípusok mindig NotInheritablevannak, egy értéktípus változója mindig ilyen típusú értéket tartalmaz. Emiatt egy értéktípus értéke nem lehet null értékű, és nem hivatkozhat származtatottabb típusú objektumra sem. Az érték típusú változóhoz való hozzárendelés létrehozza a hozzárendelt érték másolatát. Egy értéktípusú változó esetében az alapértelmezett érték annak az eredménye, hogy a típus egyes változótagjait inicializálja az alapértelmezett értékre.

Az alábbi példa a referenciatípusok és az értéktípusok közötti különbséget mutatja be:

Class Class1
    Public Value As Integer = 0
End Class

Module Test
    Sub Main()
        Dim val1 As Integer = 0
        Dim val2 As Integer = val1
        val2 = 123
        Dim ref1 As Class1 = New Class1()
        Dim ref2 As Class1 = ref1
        ref2.Value = 123
        Console.WriteLine("Values: " & val1 & ", " & val2)
        Console.WriteLine("Refs: " & ref1.Value & ", " & ref2.Value)
    End Sub
End Module

A program kimenete:

Values: 0, 123
Refs: 123, 123

A helyi változóhoz val2 való hozzárendelés nem befolyásolja a helyi változót val1 , mert mindkét helyi változó értéktípusú (típus Integer), és az értéktípus minden helyi változója saját tárolóval rendelkezik. Ezzel szemben a hozzárendelés ref2.Value = 123; hatással van arra az objektumra, amely mind a kettőre ref1ref2 hivatkozik.

A .NET-keretrendszer típusú rendszerrel kapcsolatban fontos megjegyezni, hogy bár a struktúrák, az enumerálások és a primitív típusok (kivéve String) értéktípusok, mind a referenciatípusoktól öröklődnek. A struktúrák és a primitív típusok a referenciatípustól System.ValueTypeöröklődnek Object. Az enumerált típusok a referenciatípustól System.Enumöröklődnek, amelytől örököl System.ValueType.

Null értékű értéktípusok

Értéktípusok esetén egy ? módosító hozzáadható egy típusnévhez, amely az adott típus null értékű verzióját jelöli.

NullableTypeName
    : NonArrayTypeName '?'
    ;

NullableNameModifier
    : '?'
    ;

A null értékű értéktípusok ugyanazokat az értékeket tartalmazhatják, mint a típus nem null értékű verziója, valamint a null érték. Így egy null értékű értéktípus esetében a típus változójának hozzárendelése Nothing a változó értékét null értékre állítja, nem pedig az értéktípus nulla értékére. Például:

Dim x As Integer = Nothing
Dim y As Integer? = Nothing

' Prints zero
Console.WriteLine(x)
' Prints nothing (because the value of y is the null value)
Console.WriteLine(y)

A változók null értékűnek is deklarálhatók úgy is, hogy a változó nevére egy null értékű típusmódosítót helyeznek. Az egyértelműség kedvéért érvénytelen, ha egy változónéven és egy típusnéven is null értékű típusmódosító szerepel ugyanabban a deklarációban. Mivel a null értékű típusok a típus System.Nullable(Of T)használatával vannak implementálva, a típus T? szinonimája a típusnak System.Nullable(Of T), és a két név felcserélhető. A ? módosító nem helyezhető olyan típusra, amely már null értékű, így nem deklarálható a típus Integer?? vagy System.Nullable(Of Integer)?a .

A null értékű értéktípusok T? tagjaiSystem.Nullable(Of T), valamint az alapul szolgáló típusból T a típusba T?emelt operátorok vagy átalakítások. A másolási operátorok és átalakítások megszüntetése az alapul szolgáló típusból, a legtöbb esetben a null értékű értéktípusok helyettesítése a nem null értékű értéktípusok esetében. Ez számos olyan átalakítást és műveletet tesz lehetővé, amelyek az alkalmazásra is vonatkoznak TT? .

Interfész implementálása

A struktúra- és osztálydeklarációk deklarálhatják, hogy egy vagy több Implements záradékon keresztül valósítanak meg felülettípusokat.

TypeImplementsClause
    : 'Implements' TypeImplements StatementTerminator
    ;

TypeImplements
    : NonArrayTypeName ( Comma NonArrayTypeName )*
    ;

A záradékban Implements megadott összes típusnak interfészeknek kell lennie, és a típusnak implementálnia kell az interfészek összes tagját. Például:

Interface ICloneable
    Function Clone() As Object
End Interface 

Interface IComparable
    Function CompareTo(other As Object) As Integer
End Interface 

Structure ListEntry
    Implements ICloneable, IComparable

    ...

    Public Function Clone() As Object Implements ICloneable.Clone
        ...
    End Function 

    Public Function CompareTo(other As Object) As Integer _
        Implements IComparable.CompareTo
        ...
    End Function 
End Structure

Az interfészt megvalósító típus implicit módon implementálja az interfész összes alapillesztőjét is. Ez akkor is igaz, ha a típus nem sorolja fel kifejezetten az összes alapillesztőt a Implements záradékban. Ebben a példában a struktúra mind IControlITextBoxa TextBox .

Interface IControl
    Sub Paint()
End Interface 

Interface ITextBox
    Inherits IControl

    Sub SetText(text As String)
End Interface 

Structure TextBox
    Implements ITextBox

    ...

    Public Sub Paint() Implements ITextBox.Paint
        ...
    End Sub

    Public Sub SetText(text As String) Implements ITextBox.SetText
        ...
    End Sub
End Structure

Annak deklarálása, hogy egy típus egy interfészt valósít meg önmagában és önmagában nem deklarál semmit a típus deklarációs területén. Ezért érvényes, hogy két interfészt implementáljon ugyanazzal a névvel egy metódussal.

A típusok önmagukban nem implementálhatnak típusparamétereket, bár a hatókörben lévő típusparamétereket is magukban foglalhatják.

Class C1(Of V)
    Implements V  ' Error, can't implement type parameter directly
    Implements IEnumerable(Of V)  ' OK, not directly implementing

    ...
End Class

Az általános interfészek több alkalommal is implementálhatók különböző típusú argumentumok használatával. Az általános típus azonban nem tud általános illesztőt implementálni típusparaméter használatával, ha a megadott típusparaméter (a típuskorlátozásoktól függetlenül) átfedésben lehet az adott interfész egy másik implementációjával. Például:

Interface I1(Of T)
End Interface

Class C1
    Implements I1(Of Integer)
    Implements I1(Of Double)    ' OK, no overlap
End Class

Class C2(Of T)
    Implements I1(Of Integer)
    Implements I1(Of T)         ' Error, T could be Integer
End Class

Primitív típusok

A primitív típusokat kulcsszavak azonosítják, amelyek a névtérben System előre definiált típusok aliasai. A primitív típus teljesen megkülönböztethetetlen az aliasok típusától: a fenntartott szó Byte írása pontosan ugyanaz, mint az írás System.Byte. A primitív típusokat belső típusoknak is nevezik.

PrimitiveTypeName
    : NumericTypeName
    | 'Boolean'
    | 'Date'
    | 'Char'
    | 'String'
    ;

NumericTypeName
    : IntegralTypeName
    | FloatingPointTypeName
    | 'Decimal'
    ;

IntegralTypeName
    : 'Byte' | 'SByte' | 'UShort' | 'Short' | 'UInteger'
    | 'Integer' | 'ULong' | 'Long'
    ;

FloatingPointTypeName
    : 'Single' | 'Double'
    ;

Mivel egy primitív típus normál típust aliasos, minden primitív típusnak vannak tagjai. A tagok például Integer a következőben System.Int32vannak deklarálva: . A literálok a megfelelő típusok példányaiként kezelhetők.

  • A primitív típusok abban különböznek a többi struktúratípustól, hogy bizonyos további műveleteket tesznek lehetővé:

  • A primitív típusok lehetővé teszik az értékek konstansok írásával történő létrehozását. Például 123I egy literál típusú Integer.

  • A primitív típusok állandóit deklarálhatja.

  • Ha egy kifejezés operandusai mind primitív típusú állandók, a fordító a fordításkor értékelheti ki a kifejezést. Az ilyen kifejezéseket állandó kifejezésnek nevezzük.

A Visual Basic a következő primitív típusokat határozza meg:

  • Az integrál értéktípusok Byte (1 bájt aláíratlan egész szám), SByte (1 bájt aláírt egész szám), UShort (2 bájt aláíratlan egész szám), Short (2 bájt aláírt egész szám), UInteger (4 bájt aláíratlan egész szám), Integer (4 bájtos aláírt egész szám), ULong (8 bájtos aláíratlan egész szám) és Long (8 bájtos aláírt egész szám). Ezek a típusok a következőkre vannak megfeleltetveSystem.Byte: , System.UInt16System.SByte, System.Int16, System.UInt32, System.Int32, System.UInt64 és System.Int64. Az integráltípus alapértelmezett értéke megegyezik a literál értékével 0.

  • A lebegőpontos értéktípusok Single (4 bájtos lebegőpontos) és Double a (8 bájtos lebegőpontos) Ezek a típusok megfeleltetik a megfeleltetésnek System.Single , System.Doubleilletve a megfeleltetésnek. A lebegőpontos típus alapértelmezett értéke megegyezik a literál értékével 0.

  • A Decimal típus (16 bájtos decimális érték), amely a következőre képez le: System.Decimal. A tizedes tört alapértelmezett értéke megegyezik a literál értékével 0D.

  • Az Boolean igazságértéket jelképező értéktípus általában egy relációs vagy logikai művelet eredménye. A literál típusa .System.Boolean A típus alapértelmezett értéke Boolean megegyezik a literál értékével False.

  • Az Date érték típusa, amely dátumot és/vagy időpontot jelöl, és a következőre van leképezve System.DateTime: . A típus alapértelmezett értéke Date megegyezik a literál értékével # 01/01/0001 12:00:00AM #.

  • Az Char érték típusa, amely egyetlen Unicode-karaktert jelöl, és a következőre van leképezve System.Char. A típus alapértelmezett értéke Char megegyezik az állandó kifejezéssel ChrW(0).

  • A String hivatkozás típusa, amely Unicode-karakterek sorozatát jelöli, és a következőre van leképezve System.String. A típus alapértelmezett értéke String null érték.

Számbavételek

Az enumerálások olyan értéktípusok, amelyek az egyik primitív integráltípusból öröklődnek System.Enum , és szimbolikusan egy értékhalmazt képviselnek.

EnumDeclaration
    : Attributes? TypeModifier* 'Enum' Identifier
      ( 'As' NonArrayTypeName )? StatementTerminator
      EnumMemberDeclaration+
      'End' 'Enum' StatementTerminator
    ;

Enumerálási típus Eesetén az alapértelmezett érték a kifejezés CType(0, E)által előállított érték.

Az enumerálás alapjául szolgáló típusnak olyan integráltípusnak kell lennie, amely az enumerálásban definiált összes enumerátorértéket képviselheti. Ha egy mögöttes típus van megadva, annak , SByte, UShort, Short, UInteger, Integer, , ULong, Long, vagy a System névtérben lévő megfelelő típusának kell lennieByte. Ha nincs explicit módon megadva mögöttes típus, az alapértelmezett érték az Integer.

Az alábbi példa egy enumerálást deklarál a mögöttes típussal Long:

Enum Color As Long
    Red
    Green
    Blue
End Enum

A fejlesztők dönthetnek úgy, hogy a példához hasonlóan egy mögöttes típusú Longértéket használnak, hogy lehetővé tegyék a tartományba Longtartozó, de nem a tartományba Integertartozó értékek használatát, vagy megőrizzék ezt a lehetőséget a jövőben.

Tagok számbavétele

Az enumerálás tagjai az enumerálásban deklarált számba vett értékek és az osztálytól System.Enumörökölt tagok.

Az enumerálási tagok hatóköre az enumerálási deklaráció törzse. Ez azt jelenti, hogy az enumerálási deklaráción kívül az enumerálási tagokat mindig minősíteni kell (kivéve, ha a típust névtérimportálással importálják a névtérbe).

A számbavételi tag deklarációinak deklarálási sorrendje akkor jelentős, ha az állandó kifejezésértékeket kihagyja. A számbavételi tagok csak implicit módon rendelkeznek Public hozzáféréssel; a számbavételi tag deklarációiban nem engedélyezett a hozzáférés-módosítók használata.

EnumMemberDeclaration
    : Attributes? Identifier ( Equals ConstantExpression )? StatementTerminator
    ;

Számbavételi értékek

Az enumerálási tagok listájában szereplő számba vett értékek az alapul szolgáló enumerálási típusként beírt állandókként vannak deklarálva, és bárhol megjelenhetnek, ahol szükség van rájuk. Az enumerálási tagdefiníció a = társított tag számára az állandó kifejezés által jelzett értéket adja meg. Az állandó kifejezésnek olyan integráltípusra kell kiértékelnie, amely implicit módon konvertálható az alapul szolgáló típusra, és az alapul szolgáló típus által megjeleníthető értékek tartományán belül kell lennie. Az alábbi példa hibás, mert az állandó értékek 1.5, 2.3és 3.3 nem implicit módon konvertálhatók az alapul szolgáló, szigorú szemantikával rendelkező integráltípusra Long .

Option Strict On

Enum Color As Long
    Red = 1.5
    Green = 2.3
    Blue = 3.3
End Enum

Több enumerálási tag azonos társított értékkel rendelkezhet, ahogy az alább látható:

Enum Color
    Red
    Green
    Blue
    Max = Blue
End Enum

A példa egy olyan enumerálást mutat be, amely két enumerálási taggal rendelkezik – Blue és Max –, amelyek azonos társított értékkel rendelkeznek.

Ha az enumerálás első számbavételi értékdefiníciója nem rendelkezik inicializálóval, a megfelelő állandó értéke .0 Az inicializáló nélküli enumerálási értékdefiníció az enumerátor számára az előző enumerálási érték értékének növelésével 1kapott értéket adja meg. Ennek a megnövelt értéknek az alapul szolgáló típus által ábrázolható értékek tartományán belül kell lennie.

Enum Color
    Red
    Green = 10
    Blue
End Enum 

Module Test
    Sub Main()
        Console.WriteLine(StringFromColor(Color.Red))
        Console.WriteLine(StringFromColor(Color.Green))
        Console.WriteLine(StringFromColor(Color.Blue))
    End Sub

    Function StringFromColor(c As Color) As String
        Select Case c
            Case Color.Red
                Return String.Format("Red = " & CInt(c))

            Case Color.Green
                Return String.Format("Green = " & CInt(c))

            Case Color.Blue
                Return String.Format("Blue = " & CInt(c))

            Case Else
                Return "Invalid color"
        End Select
    End Function
End Module

A fenti példa kinyomtatja az enumerálási értékeket és a hozzájuk tartozó értékeket. A kimenet a következő:

Red = 0
Green = 10
Blue = 11

Az értékek okai a következők:

  • Az enumerálási érték Red automatikusan hozzá lesz rendelve az értékhez 0 (mivel nincs inicializálója, és az első számbavételi érték tagja).

  • Az enumerálási érték Green explicit módon adja meg az értéket 10.

  • Az enumerálási érték Blue automatikusan az azt megelőző számbavételi értéknél nagyobb értékkel lesz hozzárendelve.

Az állandó kifejezés nem használhatja közvetlenül vagy közvetve a saját társított számbavételi érték értékét (vagyis az állandó kifejezés körkörössége nem engedélyezett). Az alábbi példa érvénytelen, mert a deklarációk AB körkörösek.

Enum Circular
    A = B
    B
End Enum

A B függ explicit módon, és B implicit módon függA.

Osztályok

Az osztály olyan adatszerkezet, amely tartalmazhat adattagokat (állandókat, változókat és eseményeket), függvénytagokat (metódusokat, tulajdonságokat, indexelőket, operátorokat és konstruktorokat) és beágyazott típusokat. Az osztályok referenciatípusok.

ClassDeclaration
    : Attributes? ClassModifier* 'Class' Identifier TypeParameterList? StatementTerminator
      ClassBase?
      TypeImplementsClause*
      ClassMemberDeclaration*
      'End' 'Class' StatementTerminator
    ;

ClassModifier
    : TypeModifier
    | 'MustInherit'
    | 'NotInheritable'
    | 'Partial'
    ;

Az alábbi példa egy olyan osztályt mutat be, amely minden tagtípust tartalmaz:

Class AClass
    Public Sub New()
        Console.WriteLine("Constructor")
    End Sub

    Public Sub New(value As Integer)
        MyVariable = value
        Console.WriteLine("Constructor")
    End Sub

    Public Const MyConst As Integer = 12
    Public MyVariable As Integer = 34

    Public Sub MyMethod()
        Console.WriteLine("MyClass.MyMethod")
    End Sub

    Public Property MyProperty() As Integer
        Get
            Return MyVariable
        End Get

        Set (value As Integer)
            MyVariable = value
        End Set
    End Property

    Default Public Property Item(index As Integer) As Integer
        Get
            Return 0
        End Get

        Set (value As Integer)
            Console.WriteLine("Item(" & index & ") = " & value)
        End Set
    End Property

    Public Event MyEvent()

    Friend Class MyNestedClass
    End Class 
End Class

Az alábbi példa az alábbi tagok használatát mutatja be:

Module Test

    ' Event usage.
    Dim WithEvents aInstance As AClass

    Sub Main()
        ' Constructor usage.
        Dim a As AClass = New AClass()
        Dim b As AClass = New AClass(123)

        ' Constant usage.
        Console.WriteLine("MyConst = " & AClass.MyConst)

        ' Variable usage.
        a.MyVariable += 1
        Console.WriteLine("a.MyVariable = " & a.MyVariable)

        ' Method usage.
        a.MyMethod()

        ' Property usage.
        a.MyProperty += 1
        Console.WriteLine("a.MyProperty = " & a.MyProperty)
        a(1) = 1

        ' Event usage.
        aInstance = a
    End Sub 

    Sub MyHandler() Handles aInstance.MyEvent
        Console.WriteLine("Test.MyHandler")
    End Sub 
End Module

Két osztályspecifikus módosító MustInherit és NotInheritable. Érvénytelen mindkettő megadása.

Osztály alapspecifikációja

Az osztálydeklaráció tartalmazhat olyan alaptípus-specifikációt, amely meghatározza az osztály közvetlen alaptípusát.

ClassBase
    : 'Inherits' NonArrayTypeName StatementTerminator
    ;

Ha egy osztálydeklaráció nem rendelkezik explicit alaptípussal, a közvetlen alaptípus implicit módon Objecttörténik. Például:

Class Base
End Class

Class Derived
    Inherits Base
End Class

Az alaptípusok önmagukban nem lehetnek típusparaméterek, bár a hatókörben lévő típusparamétereket is magukban foglalhatják.

Class C1(Of V) 
End Class

Class C2(Of V)
    Inherits V    ' Error, type parameter used as base class 
End Class

Class C3(Of V)
    Inherits C1(Of V)    ' OK: not directly inheriting from V.
End Class

Az osztályok csak ezekből és osztályokból Object származhatnak. Érvénytelen, ha egy osztályból származik System.ValueType, System.Enumvagy System.DelegateSystem.ArraySystem.MulticastDelegate . Az általános osztályok nem származtathatók System.Attribute abból vagy abból származó osztályból.

Minden osztálynak pontosan egy közvetlen alaposztálya van, és a származtatás körkörössége tilos. Nem lehet osztályból NotInheritable származni, és az alaposztály akadálymentességi tartományának meg kell egyeznie az osztály akadálymentességi tartományával vagy annak egy szuperhalmazával.

Osztálytagok

Az osztály tagjai az osztálytagok nyilatkozatai által bevezetett tagokból és a közvetlen alaposztályból öröklődő tagokból állnak.

ClassMemberDeclaration
    : NonModuleDeclaration
    | EventMemberDeclaration
    | VariableMemberDeclaration
    | ConstantMemberDeclaration
    | MethodMemberDeclaration
    | PropertyMemberDeclaration
    | ConstructorMemberDeclaration
    | OperatorDeclaration
    ;

Az osztálytagok deklarációja Publicrendelkezhet , Protected, Friend, Protected Friendvagy Private hozzáféréssel. Ha egy osztálytag-deklaráció nem tartalmaz hozzáférési módosítót, a deklaráció alapértelmezés szerint a hozzáférésre Public vonatkozik, kivéve, ha változó deklarációról van szó; ebben az esetben alapértelmezés szerint a hozzáférés.Private

Az osztálytagok hatóköre az osztály törzse, amelyben a tag deklarációja történik, valamint az osztály kényszerlistája (ha általános, és korlátozásokkal rendelkezik). Ha a tag rendelkezik Friend hozzáféréssel, hatóköre az ugyanabban a programban vagy bármely olyan szerelvényben lévő származtatott osztály osztálytörzsére terjed ki, amely hozzáférést kapottFriend, és ha a tag rendelkezik hozzáféréssel, Protectedvagy Protected Friend hozzáféréssel rendelkezikPublic, hatóköre bármely program származtatott osztályának osztálytörzsére terjed ki.

Struktúrák

A struktúrák olyan értéktípusok, amelyektől öröklődnek System.ValueType. A struktúrák hasonlóak az osztályokhoz, amelyek adatstruktúrákat jelölnek, amelyek adattagokat és függvénytagokat tartalmazhatnak. Az osztályoktól eltérően azonban a struktúrák nem igényelnek halomfoglalást.

StructureDeclaration
    : Attributes? StructureModifier* 'Structure' Identifier
      TypeParameterList? StatementTerminator
      TypeImplementsClause*
      StructMemberDeclaration*
      'End' 'Structure' StatementTerminator
    ;

StructureModifier
    : TypeModifier
    | 'Partial'
    ;

Osztályok esetében két változó hivatkozhat ugyanarra az objektumra, és így az egyik változón végzett műveletek hatással lehetnek a másik változó által hivatkozott objektumra. A struktúrák esetében a változók mindegyike saját másolattal rendelkezik a nemShared adatokról, így az egyiken végzett műveletek nem befolyásolhatják a másikat, ahogy az alábbi példa szemlélteti:

Structure Point
    Public x, y As Integer

    Public Sub New(x As Integer, y As Integer)
        Me.x = x
        Me.y = y
    End Sub
End Structure

A fenti deklaráció alapján a következő kód adja ki az értéket 10:

Module Test
    Sub Main()
        Dim a As New Point(10, 10)
        Dim b As Point = a

        a.x = 100
        Console.WriteLine(b.x)
    End Sub
End Module

A hozzárendelés ab az érték másolatát hozza létre, és b így a hozzárendelés a.xnem érinti. Ha Point ehelyett osztályként lett deklarálva, a kimenet azért lett 100 volna, mert ab ugyanarra az objektumra hivatkozna.

Tagstruktúra

A struktúra tagjai azok a tagok, amelyeket a szervezeti tag deklarációi vezetnek be, és a tagok, amelyektől System.ValueTypeöröklődtek.

StructMemberDeclaration
    : NonModuleDeclaration
    | VariableMemberDeclaration
    | ConstantMemberDeclaration
    | EventMemberDeclaration
    | MethodMemberDeclaration
    | PropertyMemberDeclaration
    | ConstructorMemberDeclaration
    | OperatorDeclaration
    ;

Minden struktúra implicit módon rendelkezik egy Public paraméter nélküli példánykonstruktorsal, amely a struktúra alapértelmezett értékét állítja elő. Emiatt a struktúratípus-deklaráció nem deklarálhat paraméter nélküli példánykonstruktort. A struktúratípus azonban lehetővé teszi a paraméteres példánykonstruktorok deklarálásához, ahogyan az alábbi példában is látható:

Structure Point
    Private x, y As Integer

    Public Sub New(x As Integer, y As Integer)
        Me.x = x
        Me.y = y
    End Sub
End Structure

A fenti deklaráció alapján a következő utasítások egy nullával rendelkező x és y inicializált utasítást Point is létrehoznak.

Dim p1 As Point = New Point()
Dim p2 As Point = New Point(0, 0)

Mivel a struktúrák közvetlenül tartalmazzák a mezőértékeiket (ahelyett, hogy ezekre az értékekre hivatkoznak), a struktúrák nem tartalmazhatnak olyan mezőket, amelyek közvetlenül vagy közvetve magukra hivatkoznak. Például a következő kód érvénytelen:

Structure S1
    Dim f1 As S2
End Structure

Structure S2
    ' This would require S1 to contain itself.
    Dim f1 As S1
End Structure

A struktúratagok deklarációja általában csak , Friendvagy hozzáféréssel rendelkezhetPublic, de ha felül kell bírálni a tagok öröklött tagjaitObject, Protected és Protected Friend a hozzáférés is Private használható. Ha a struktúratag-deklaráció nem tartalmaz hozzáférési módosítót, a deklaráció alapértelmezés szerint a hozzáférésre Public vonatkozik. A struktúra által deklarált tag hatóköre az a struktúratörzs, amelyben a deklaráció történik, valamint az adott struktúra korlátai (ha általános volt, és kényszerek voltak).

Standard modulok

A standard modul olyan típus, amelynek tagjai implicit módon Shared és hatókörrel vannak elosztva a standard modul névterét tartalmazó deklarációs területére, nem csak a standard modul deklarációjára. Előfordulhat, hogy a standard modulok soha nem lesznek példányosítva. Hiba egy standard modultípusú változó deklarálása.

ModuleDeclaration
    : Attributes? TypeModifier* 'Module' Identifier StatementTerminator
      ModuleMemberDeclaration*
      'End' 'Module' StatementTerminator
    ;

A standard modul egy tagja két teljesen minősített névvel rendelkezik, az egyik a standard modul neve nélkül, a másik pedig a standard modul nevével. Egy névtérben egynél több szabványos modul definiálhat egy tagot egy adott névvel; a modulon kívüli névre való nem minősített hivatkozások nem egyértelműek. Például:

Namespace N1
    Module M1
        Sub S1()
        End Sub

        Sub S2()
        End Sub
    End Module

    Module M2
        Sub S2()
        End Sub
    End Module

    Module M3
        Sub Main()
            S1()       ' Valid: Calls N1.M1.S1.
            N1.S1()    ' Valid: Calls N1.M1.S1.
            S2()       ' Not valid: ambiguous.
            N1.S2()    ' Not valid: ambiguous.
            N1.M2.S2() ' Valid: Calls N1.M2.S2.
        End Sub
    End Module
End Namespace

Egy modul csak névtérben deklarálható, és más típusba nem ágyazható be. A standard modulok nem implementálhatnak interfészeket, implicit módon származnak, Objectés csak Shared konstruktorokkal rendelkeznek.

Standard modultagok

A standard modul tagjai a tagbevallások által bevezetett tagok és a tagok, amelyektől Objectöröklötték a tagokat. A standard modulok bármilyen tagtípussal rendelkezhetnek, kivéve a példánykonstruktorokat. Az összes standard modultípus-tag implicit módon Sharedvan.

ModuleMemberDeclaration
    : NonModuleDeclaration
    | VariableMemberDeclaration
    | ConstantMemberDeclaration
    | EventMemberDeclaration
    | MethodMemberDeclaration
    | PropertyMemberDeclaration
    | ConstructorMemberDeclaration
    ;

Normál modultag-deklaráció általában csak , Friendvagy hozzáféréssel rendelkezhetPublic, de ha felül kell bírálni az örökölt Objecttagokat, meg lehet adni a Protected hozzáférési módosítókat.Protected FriendPrivate Ha egy standard modultag-deklaráció nem tartalmaz hozzáférési módosítót, a deklaráció alapértelmezés szerint a hozzáférésre Public vonatkozik, hacsak nem változó, amely alapértelmezés szerint Private hozzáfér.

Ahogy korábban említettük, a standard modultagok hatóköre a standard moduldeklarációt tartalmazó deklaráció. Ebben a speciális hatókörben nem szerepelnek az örökölt Object tagok; ezek a tagok nem rendelkeznek hatókörrel, és mindig a modul nevével kell rendelkezniük. Ha a tag rendelkezik Friend hozzáféréssel, hatóköre csak az ugyanazon programban deklarált névtértagokra vagy a hozzáféréssel rendelkező Friend szerelvényekre terjed ki.

Felületek

Az interfészek olyan referenciatípusok, amelyeket más típusok implementálnak, hogy garantálják bizonyos módszerek támogatását. Az illesztő soha nem jön létre közvetlenül, és nincs tényleges ábrázolása – más típusokat illesztőtípussá kell konvertálni. Az interfész egy szerződést határoz meg. Az interfészt megvalósító osztálynak vagy struktúrának be kell tartania a szerződését.

InterfaceDeclaration
    : Attributes? TypeModifier* 'Interface' Identifier
      TypeParameterList? StatementTerminator
      InterfaceBase*
      InterfaceMemberDeclaration*
      'End' 'Interface' StatementTerminator
    ;

Az alábbi példa egy alapértelmezett tulajdonságot Item, eseményt E, metódust Fés tulajdonságot Ptartalmazó felületet mutat be:

Interface IExample
    Default Property Item(index As Integer) As String

    Event E()

    Sub F(value As Integer)

    Property P() As String
End Interface

Az interfészek több öröklést is alkalmazhatnak. Az alábbi példában a felület IComboBox mindkét ITextBox és IListBoxa következőtől öröklődik:

Interface IControl
    Sub Paint()
End Interface 

Interface ITextBox
    Inherits IControl

    Sub SetText(text As String)
End Interface 

Interface IListBox
    Inherits IControl

    Sub SetItems(items() As String)
End Interface 

Interface IComboBox
    Inherits ITextBox, IListBox 
End Interface

Az osztályok és struktúrák több interfészt is implementálhatnak. Az alábbi példában az osztály EditBox az osztályból Control származik, és mindkettőt IControl és IDataBound:

Interface IDataBound
    Sub Bind(b As Binder)
End Interface 

Public Class EditBox
    Inherits Control
    Implements IControl, IDataBound

    Public Sub Paint() Implements IControl.Paint
        ...
    End Sub

    Public Sub Bind(b As Binder) Implements IDataBound.Bind
        ...
    End Sub
End Class

Interfész öröklése

Az interfészek alapfelületei az explicit alapfelületek és azok alapfelületei. Más szóval az alapinterfészek halmaza az explicit alapinterfészek, azok explicit alapinterfészeinek teljes tranzitív lezárása, és így tovább. Ha egy felületi deklaráció nem rendelkezik explicit felületi alapokkal, akkor a típushoz nincs alapfelület – az interfészek nem örökölnek Object (bár az illesztőknek van egy kibővítő konverziójuk Object).

InterfaceBase
    : 'Inherits' InterfaceBases StatementTerminator
    ;

InterfaceBases
    : NonArrayTypeName ( Comma NonArrayTypeName )*
    ;

Az alábbi példában a következők alapillesztői IComboBox a következők IControl: , ITextBoxés IListBox.

Interface IControl
    Sub Paint()
End Interface 

Interface ITextBox
    Inherits IControl

    Sub SetText(text As String)
End Interface 

Interface IListBox
    Inherits IControl

    Sub SetItems(items() As String)
End Interface 

Interface IComboBox
    Inherits ITextBox, IListBox 
End Interface

Az interfész örökli az alapfelületek összes tagját. Más szóval, a IComboBox fenti felület örökli a tagokat SetText és SetItems, valamint Paint is.

Az interfészt megvalósító osztály vagy struktúra implicit módon implementálja az interfész összes alapfelületét is.

Ha egy interfész többször jelenik meg az alap interfészek tranzitív lezárásakor, csak egyszer járul hozzá tagjaihoz a származtatott interfészhez. A származtatott interfészt implementáló típusnak csak egyszer kell implementálnia a szorzott alapfelület metódusait. A következő példában Paint csak egyszer kell implementálni, még akkor is, ha az osztály implementálja IComboBox és IControl.

Class ComboBox
    Implements IControl, IComboBox

    Sub SetText(text As String) Implements IComboBox.SetText
    End Sub

    Sub SetItems(items() As String) Implements IComboBox.SetItems
    End Sub

    Sub Print() Implements IComboBox.Paint
    End Sub
End Class

A Inherits záradéknak nincs hatása más Inherits záradékokra. Az alábbi példában IDerived a következő névnek kell megfelelnieIBaseINested:

Interface IBase
    Interface INested
        Sub Nested()
    End Interface

    Sub Base()
End Interface

Interface IDerived
    Inherits IBase, INested   ' Error: Must specify IBase.INested.
End Interface

Az alapfelület akadálymentességi tartományának meg kell egyeznie a felület akadálymentességi tartományával vagy annak egy szuperhalmazával.

Interfésztagok

Az interfész tagjai a tagnyilatkozatai által bevezetett tagokból és az alapfelületekből öröklődő tagokból állnak.

InterfaceMemberDeclaration
    : NonModuleDeclaration
    | InterfaceEventMemberDeclaration
    | InterfaceMethodMemberDeclaration
    | InterfacePropertyMemberDeclaration
    ;

Bár az interfészek nem öröklik a tagokat Object, mivel minden olyan osztály vagy struktúra, amely egy interfészt implementál, örökölObject, a Objectbővítménymetszeteket is beleértve, egy felület tagjainak tekintik, és közvetlenül meghívhatók egy interfészre anélkül, hogy leadást igényelnek.Object Például:

Interface I1
End Interface

Class C1
    Implements I1
End Class

Module Test
    Sub Main()
        Dim i As I1 = New C1()
        Dim h As Integer = i.GetHashCode()
    End Sub
End Module

Az implicit árnyéktagok Object tagjaival Object azonos nevű felület tagjai. Csak beágyazott típusok, metódusok, tulajdonságok és események lehetnek a felület tagjai. Előfordulhat, hogy a metódusoknak és tulajdonságoknak nincs törzse. A felület tagjai implicit módon Public vannak megadva, és nem adhatnak meg hozzáférési módosítót. Az interfészben deklarált tag hatóköre az interfész törzse, amelyben a deklaráció történik, valamint az interfész kényszerlistája (ha általános, és korlátozásokkal rendelkezik).

Tömbök

A tömb olyan referenciatípus, amely a tömb változóinak sorrendjével egy-az-egyhez típusú indexeken keresztül elért változókat tartalmaz. A tömbben található változóknak, más néven a tömb elemeinek azonos típusúnak kell lenniük, és ezt a típust a tömb elemtípusának nevezzük.

ArrayTypeName
    : NonArrayTypeName ArrayTypeModifiers
    ;

ArrayTypeModifiers
    : ArrayTypeModifier+
    ;

ArrayTypeModifier
    : OpenParenthesis RankList? CloseParenthesis
    ;

RankList
    : Comma*
    ;

ArrayNameModifier
    : ArrayTypeModifiers
    | ArraySizeInitializationModifier
    ;

A tömb elemei egy tömbpéldány létrehozásakor jönnek létre, és a tömbpéldány megsemmisítésekor megszűnnek. A tömb minden eleme inicializálva lesz a típus alapértelmezett értékére. Ez a típus System.Array az összes tömbtípus alaptípusa, ezért előfordulhat, hogy nem példányosít. Minden tömbtípus örökli a típus által System.Array deklarált tagokat, és átalakítható rá (és Object). Az elemekkel T rendelkező egydimenziós tömbtípusok implementálják az interfészeket System.Collections.Generic.IList(Of T) , és IReadOnlyList(Of T)– ha T referenciatípus – a tömbtípus is implementálható IList(Of U) , és IReadOnlyList(Of U) minden U olyan típus esetében, amelyből a referenciakonvertálás Tszélesedik.

A tömbök rangsora határozza meg az egyes tömbelemekhez társított indexek számát. A tömb rangja határozza meg a tömb dimenzióinak számát. Egy rangot tartalmazó tömböt például egydimenziós tömbnek, egynél nagyobb rangot tartalmazó tömböt pedig többdimenziós tömbnek nevezünk.

Az alábbi példa egy egész számból álló egydimenziós tömböt hoz létre, inicializálja a tömbelemeket, majd kinyomtatja őket:

Module Test
    Sub Main()
        Dim arr(5) As Integer
        Dim i As Integer

        For i = 0 To arr.Length - 1
            arr(i) = i * i
        Next i

        For i = 0 To arr.Length - 1
            Console.WriteLine("arr(" & i & ") = " & arr(i))
        Next i
    End Sub
End Module

A program a következőket adja ki:

arr(0) = 0
arr(1) = 1
arr(2) = 4
arr(3) = 9
arr(4) = 16
arr(5) = 25

A tömbök minden dimenziója rendelkezik egy társított hosszúságsal. A dimenzióhosszok nem részei a tömb típusának, hanem akkor jönnek létre, ha a tömbtípus egy példánya futásidőben jön létre. A dimenzió hossza határozza meg az adott dimenzióra vonatkozó indexek érvényes tartományát: egy hosszúsági Ndimenzió esetében az indexek nullától a 0-ig N-1terjedhetnek. Ha egy dimenzió nulla hosszúságú, akkor az adott dimenzióra nincsenek érvényes indexek. A tömb elemeinek teljes száma a tömb egyes dimenzióinak hosszának szorzata. Ha egy tömb bármely dimenziója nulla hosszúságú, akkor a tömb üresnek minősül. A tömb elemtípusa bármilyen típusú lehet.

A tömbtípusok egy módosító meglévő típusnévhez való hozzáadásával vannak megadva. A módosító bal zárójelből, nulla vagy több vesszőből és jobb zárójelből áll. A módosított típus a tömb elemtípusa, a dimenziók száma pedig a vesszők száma plusz egy. Ha több módosító van megadva, akkor a tömb elemtípusa tömb. A módosítók balról jobbra olvashatók, a bal szélső módosító pedig a legkülső tömb. A példában

Module Test
    Dim arr As Integer(,)(,,)()
End Module

az elem típusa arr egy kétdimenziós tömb, amely egydimenziós tömbök háromdimenziós tömbjeiből áll Integer.

A változók tömbtípusúnak is deklarálhatók úgy, hogy tömbtípus-módosító vagy tömbméretű inicializálási módosító kerül a változó nevére. Ebben az esetben a tömbelem típusa a deklarációban megadott típus, a tömbdimenziókat pedig a változónév-módosító határozza meg. Az egyértelműség kedvéért nem érvényes, hogy egy tömbtípus-módosító egy változónéven és egy típusnéven is szerepeljen ugyanabban a deklarációban.

Az alábbi példa számos olyan helyi változódeklarációt mutat be, amelyek tömbtípusokat Integer használnak elemtípusként:

Module Test
    Sub Main()
        Dim a1() As Integer    ' Declares 1-dimensional array of integers.
        Dim a2(,) As Integer   ' Declares 2-dimensional array of integers.
        Dim a3(,,) As Integer  ' Declares 3-dimensional array of integers.

        Dim a4 As Integer()    ' Declares 1-dimensional array of integers.
        Dim a5 As Integer(,)   ' Declares 2-dimensional array of integers.
        Dim a6 As Integer(,,)  ' Declares 3-dimensional array of integers.

        ' Declare 1-dimensional array of 2-dimensional arrays of integers 
        Dim a7()(,) As Integer
        ' Declare 2-dimensional array of 1-dimensional arrays of integers.
        Dim a8(,)() As Integer

        Dim a9() As Integer() ' Not allowed.
    End Sub
End Module

A tömbtípusnév-módosító az azt követő összes zárójelkészletre kiterjed. Ez azt jelenti, hogy olyan helyzetekben, amikor a zárójelben lévő argumentumok egy típusnév után engedélyezettek, nem lehet megadni a tömbtípusnév argumentumait. Például:

Module Test
    Sub Main()
        ' This calls the Integer constructor.
        Dim x As New Integer(3)

        ' This declares a variable of Integer().
        Dim y As Integer()

        ' This gives an error.
        ' Array sizes can not be specified in a type name.
        Dim z As Integer()(3)
    End Sub
End Module

Az utolsó esetben a rendszer a típusnév részeként értelmezi, (3) nem pedig konstruktorargumentumok halmazaként.

Delegáltak

A meghatalmazott olyan referenciatípus, amely egy típus vagy egy objektum példánymetódusára hivatkozik Shared .

DelegateDeclaration
    : Attributes? TypeModifier* 'Delegate' MethodSignature StatementTerminator
    ;

MethodSignature
    : SubSignature
    | FunctionSignature
    ;

Más nyelveken a delegált legközelebbi megfelelője a függvénymutató, de míg a függvénymutatók csak függvényre hivatkozhatnak Shared , a meghatalmazottak hivatkozhatnak mindkettőre és a példány metódusára is Shared . Az utóbbi esetben a delegált nem csak a metódus belépési pontjára mutató hivatkozást, hanem arra az objektumpéldányra mutató hivatkozást is tárol, amellyel meghívhatja a metódust.

A deklaráció nem rendelkezhet záradékkal Handles , záradékkal Implements , metódustörzstel vagy szerkezettel End . A delegált deklaráció paraméterlistája nem tartalmazhat és ParamArray nem tartalmazhat Optional paramétereket. A visszatérési típus és a paramétertípusok akadálymentességi tartományának meg kell egyeznie a delegált akadálymentességi tartományával vagy egy szuperhalmazával.

A meghatalmazott tagjai az osztálytól System.Delegateörökölt tagok. A meghatalmazott a következő módszereket is meghatározza:

  • Egy konstruktor, amely két paramétert, egy típust Object és egy típust System.IntPtrvesz igénybe.

  • Olyan Invoke metódus, amelynek aláírása megegyezik a meghatalmazott aláírásával.

  • Egy BeginInvoke metódus, amelynek aláírása a delegált aláírás, három különbséggel. Először a visszatérési típus a következőre System.IAsyncResultmódosul: . Másodszor két további paramétert ad hozzá a paraméterlista végéhez: az első típust System.AsyncCallback és a második típust Object. Végül az összes ByRef paraméter ByValmódosul.

  • Olyan EndInvoke metódus, amelynek visszatérési típusa megegyezik a meghatalmazottéval. A metódus paraméterei csak azok a delegált paraméterek, amelyek ByRef pontosan paraméterek, ugyanabban a sorrendben, mint a delegált aláírásban. Ezen paraméterek mellett egy további típusú System.IAsyncResult paraméter is található a paraméterlista végén.

A meghatalmazottak definiálásának és használatának három lépése van: deklaráció, példányosítás és hívás.

A meghatalmazottak deklarálása deklarálási szintaxissal történik. Az alábbi példa egy olyan meghatalmazottat SimpleDelegate deklarál, amely nem vesz fel argumentumokat:

Delegate Sub SimpleDelegate()

A következő példa létrehoz egy példányt SimpleDelegate , majd azonnal meghívja:

Module Test
    Sub F()
        System.Console.WriteLine("Test.F")
    End Sub 

    Sub Main()
        Dim d As SimpleDelegate = AddressOf F
        d()
    End Sub 
End Module

Nincs sok értelme a metódushoz tartozó meghatalmazott példányosításának, majd a meghatalmazotton keresztüli azonnali hívásnak, mivel egyszerűbb lenne közvetlenül meghívni a metódust. A meghatalmazottak az anonimitásuk használatakor jelzik a hasznosságukat. A következő példa egy olyan metódust MultiCall mutat be, amely ismételten meghív egy példányt SimpleDelegate :

Sub MultiCall(d As SimpleDelegate, count As Integer)
    Dim i As Integer

    For i = 0 To count - 1
        d()
    Next i
End Sub

A metódus szempontjából nem lényeges, hogy MultiCall mi a célmetódus, milyen akadálymentességgel rendelkezik ez a SimpleDelegate módszer, vagy hogy a metódus vagy Shared sem. Csak az számít, hogy a célmetódus aláírása kompatibilis-e a következővel SimpleDelegate: .

Részleges típusok

Az osztály- és szerkezetdeklarációk lehetnek részleges deklarációk. A részleges deklaráció a deklarált típust a deklarációban vagy nem feltétlenül írja le teljes egészében. Ehelyett a típus deklarációja több részleges deklarációra is kiterjedhet a programban; a részleges típusok nem deklarálhatók a programhatárok között. A részleges típusdeklaráció a Partial deklaráció módosító karakterét adja meg. Ezután a program minden más deklarációja egy azonos, teljes névvel rendelkező típus esetében a fordítási időpontban a részleges deklarációval együtt egyetlen típusdeklarációt hoz létre. Az alábbi kód például egyetlen osztályt Test deklarál tagokkal Test.C1 és Test.C2.

a.vb:

Public Partial Class Test
    Public Sub S1()
    End Sub
End Class

b.vb:

Public Class Test
    Public Sub S2()
    End Sub
End Class

Részleges típusdeklarációk kombinálásakor a deklarációk legalább egyikének módosítóval kell rendelkeznie Partial , ellenkező esetben fordítási idejű hibaeredményeket kell eredményeznie.

Jegyzet. Bár a sok részleges deklaráció közül csak egy deklarációt lehet megadni Partial , célszerűbb az összes részleges deklaráción megadni. Abban az esetben, ha egy részleges deklaráció látható, de egy vagy több részleges deklaráció rejtett (például az eszköz által generált kód kiterjesztése esetén), elfogadható, ha a Partial módosítót a látható deklarációból hagyja, de a rejtett deklarációkban meg kell adnia.

Csak osztályok és struktúrák deklarálhatók részleges deklarációkkal. A típus aritását akkor veszi figyelembe, ha a részleges deklarációk egyezőek: két azonos nevű, de eltérő számú típusparaméterrel rendelkező osztály nem tekinthető azonos idejű részleges deklarációnak. A részleges deklarációk attribútumokat, osztálymódosítókat, Inherits utasítást vagy Implements utasítást adhatnak meg. Fordításkor a részleges deklarációk összes darabja össze lesz kötve, és a típusdeklaráció részeként lesz felhasználva. Ha ütközések vannak az attribútumok, módosítók, bázisok, interfészek vagy típustagok között, fordítási idő hibát eredményez. Például:

Public Partial Class Test1
    Implements IDisposable
End Class

Class Test1
    Inherits Object
    Implements IComparable
End Class

Public Partial Class Test2
End Class

Private Partial Class Test2
End Class

Az előző példa egy olyan típust Test1 deklarál, amely Publicörökli Object és implementálja System.IDisposable azokat.System.IComparable A részleges deklarációk Test2 fordítási időt eredményeznek, mert az egyik deklaráció azt mondja, hogy Test2 ez, Public a másik pedig azt mondja, hogy Test2 az Private.

A típusparaméterekkel rendelkező részleges típusok deklarálhatják a típusparaméterek kényszereit és varianciáját, de az egyes részleges deklarációk kényszereinek és varianciájának meg kell egyeznie. Így a kényszerek és a variancia különlegesek, mivel nem kombinálódnak automatikusan, mint más módosítók:

Partial Public Class List(Of T As IEnumerable)
End Class

' Error: Constraints on T don't match
Class List(Of T As IComparable)
End Class

Az a tény, hogy egy típus több részleges deklarációval van deklarálva, nincs hatással a típuson belüli névkeresési szabályokra. Ennek eredményeképpen a részleges típusdeklarációk használhatják az egyéb részleges típusdeklarációkban deklarált tagokat, vagy más részleges típusdeklarációkban deklarált felületeken implementálhatnak metódusokat. Például:

Public Partial Class Test1
    Implements IDisposable

    Private IsDisposed As Boolean = False
End Class

Class Test1
    Private Sub Dispose() Implements IDisposable.Dispose
        If Not IsDisposed Then
            ...
        End If
    End Sub
End Class

A beágyazott típusok részleges deklarációkkal is rendelkezhetnek. Például:

Public Partial Class Test
    Public Partial Class NestedTest
        Public Sub S1()
        End Sub
    End Class
End Class

Public Partial Class Test
    Public Partial Class NestedTest
        Public Sub S2()
        End Sub
    End Class
End Class

A részleges deklaráción belüli inicializálók továbbra is deklarációs sorrendben lesznek végrehajtva; azonban nincs garantált végrehajtási sorrend az inicializálók számára, amelyek külön részleges deklarációkban fordulnak elő.

Konstruktált típusok

Az általános típusdeklaráció önmagában nem jelöl típust. Ehelyett egy általános típusdeklaráció használható "tervként" számos különböző típus létrehozásához típusargumentumok alkalmazásával. A típusargumentumokkal rendelkező általános típusokat konstruált típusnak nevezzük. A létrehozott típus argumentumainak mindig meg kell felelniük azoknak a típusparamétereknek, amelyeknek megfelelnek.

A típusnév akkor is azonosíthat egy létrehozott típust, ha közvetlenül nem ad meg típusparamétereket. Ez akkor fordulhat elő, ha egy típus egy általános osztálydeklarációban van beágyazva, és a rendszer implicit módon használja a névkereséshez a tartalmazó deklaráció példánytípusát:

Class Outer(Of T) 
    Public Class Inner 
    End Class

    ' Type of i is the constructed type Outer(Of T).Inner
    Public i As Inner 
End Class

A létrehozott típus C(Of T1,...,Tn) akkor érhető el, ha az általános típus és az összes típusargumentum elérhető. Ha például az általános típusC, Public és az összes típusargumentumT1,...,Tn, Publicakkor a létrehozott típus .Public Ha azonban a típusnév vagy a típusargumentumok Privateegyike, akkor a létrehozott típus akadálymentessége .Private Ha a létrehozott típus Protected egyik típusargumentuma és egy másik típusargumentum Friend, akkor a létrehozott típus csak az osztályban és annak alosztályaiban érhető el ebben a szerelvényben vagy bármely olyan szerelvényben, amely hozzáférést kapott Friend . Más szóval, a létrehozott típus akadálymentességi tartománya az összetevők akadálymentességi tartományainak metszete.

Jegyzet. Az a tény, hogy az épített típus akadálymentességi területe a létrehozott részek metszete, érdekes mellékhatása egy új akadálymentességi szint meghatározásának. Olyan létrehozott típus, amely olyan elemet tartalmaz, amely olyan Protected elemet tartalmaz, amely Friend csak olyan környezetekben érhető el, amelyek minda tagokhoz, mindFriendProtected a tagokhoz hozzáférnek. Ezt az akadálymentességi szintet azonban nem lehet a nyelven kifejezni, mivel az akadálymentesség Protected Friend azt jelenti, hogy egy entitás egy olyan környezetben érhető el, amely vagy aFriendProtectedtagok számára elérhető.

Az alap, a implementált illesztők és a létrehozott típusok tagjai a megadott típusargumentumok helyettesítésével határozhatók meg a típusparaméter minden előfordulásához az általános típusban.

Nyitott típusok és zárt típusok

Nyitott típusnak nevezzük azt a típustípust, amelynek egy vagy több típusargumentuma egy adott típus vagy metódus típusparamétere. Ennek az az oka, hogy a típus egyes típusparaméterei még mindig nem ismertek, így a típus tényleges alakja még nem teljesen ismert. Ezzel szemben egy olyan általános típust, amelynek típusargumentumai mind nem típusparaméterek, zárt típusnak nevezzük. A zárt típus alakja mindig teljes mértékben ismert. Például:

Class Base(Of T, V)
End Class

Class Derived(Of V)
    Inherits Base(Of Integer, V)
End Class

Class MoreDerived
    Inherits Derived(Of Double)
End Class

A létrehozott típus Base(Of Integer, V) nyitott típus, mert bár a típusparaméter T meg lett adva, a típusparaméter U egy másik típusparamétert kapott. Így a típus teljes alakja még nem ismert. A létrehozott típus Derived(Of Double)azonban zárt típus, mivel az öröklési hierarchiában minden típusparaméter meg lett adva.

A nyitott típusok a következőképpen vannak definiálva:

  • A típusparaméter egy nyitott típus.

  • A tömbtípus nyitott típus, ha az elemtípusa nyitott típus.

  • A létrehozott típus nyitott típus, ha egy vagy több típusargumentum nyitott típus.

  • A zárt típus olyan típus, amely nem nyitott típus.

Mivel a program belépési pontja nem lehet általános típus, a futtatáskor használt összes típus zárt típusok lesznek.

Speciális típusok

A .NET-keretrendszer számos osztályt tartalmaz, amelyeket kifejezetten a .NET-keretrendszer és a Visual Basic nyelv kezel:

A .NET-keretrendszer üres típusát képviselő típusra System.Voidközvetlenül csak kifejezésekben GetType lehet hivatkozni.

A típusok System.RuntimeArgumentHandleés System.ArgIteratorSystem.TypedReference az összes tartalmazhat mutatót a verembe, ezért nem jelennek meg a .NET-keretrendszer halomán. Ezért nem használhatók tömbelem-típusokként, visszatérési típusokként, mezőtípusokként, általános típusargumentumokként, null értékű típusokként, paramétertípusokként, ByRef az átalakítandó Object érték típusához vagy System.ValueType, a példány tagjaihoz ObjectSystem.ValueTypevagy , vagy lezárásba emelt hívás céljához.