Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Dvě základní kategorie typů v jazyce Visual Basic jsou typy hodnot a odkazové typy. Primitivní typy (kromě řetězců), výčty a struktury jsou typy hodnot. Třídy, řetězce, standardní moduly, rozhraní, pole a delegáty jsou odkazové typy.
Každý typ má výchozí hodnotu, což je hodnota přiřazená proměnným tohoto typu při inicializaci.
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?
;
Typy hodnot a odkazové typy
I když typy hodnot a odkazové typy můžou být podobné z hlediska syntaxe deklarace a použití, jejich sémantika je odlišná.
Odkazové typy jsou uloženy v haldě za běhu; mohou být přístupné pouze prostřednictvím odkazu na toto úložiště. Vzhledem k tomu, že k typům odkazů se vždy přistupuje prostřednictvím odkazů, je jejich životnost spravována rozhraním .NET Framework. Nevyřízené odkazy na konkrétní instanci jsou sledovány a instance je zničena pouze v případě, že žádné další odkazy nezůstanou. Proměnná typu odkazu obsahuje odkaz na hodnotu tohoto typu, hodnotu odvozeného typu nebo hodnotu null. Hodnota null odkazuje na nic; Není možné nic dělat s hodnotou null s výjimkou přiřazení. Přiřazení proměnné typu odkazu vytvoří kopii odkazu místo kopie odkazované hodnoty. Pro proměnnou typu odkazu je výchozí hodnota null.
Typy hodnot jsou uloženy přímo v zásobníku, a to buď v poli, nebo v jiném typu; k jejich úložišti je možné přistupovat pouze přímo. Vzhledem k tomu, že typy hodnot jsou uloženy přímo v proměnných, jejich životnost je určena životností proměnné, která je obsahuje. Pokud je umístění obsahující instanci typu hodnoty zničeno, instance typu hodnoty je také zničena. K typům hodnot se vždy přistupuje přímo; Není možné vytvořit odkaz na typ hodnoty. Zakázání takového odkazu znemožňuje odkazovat na instanci třídy hodnot, která byla zničena. Vzhledem k tomu, že typy hodnot jsou vždy NotInheritable, proměnná typu hodnoty vždy obsahuje hodnotu tohoto typu. Z tohoto důvodu nemůže být hodnota typu hodnoty null, ani nemůže odkazovat na objekt odvozeného typu. Přiřazení proměnné typu hodnoty vytvoří kopii přiřazené hodnoty. Pro proměnnou typu hodnoty je výchozí hodnota výsledkem inicializace každého člena proměnné typu na výchozí hodnotu.
Následující příklad ukazuje rozdíl mezi odkazovými typy a typy hodnot:
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
Výstupem programu je:
Values: 0, 123
Refs: 123, 123
Přiřazení k místní proměnné val2 nemá vliv na místní proměnnou val1 , protože obě místní proměnné mají typ hodnoty (typ Integer) a každá místní proměnná typu hodnoty má vlastní úložiště. Naproti tomu přiřazení ref2.Value = 123; ovlivňuje objekt, který a ref1ref2 odkazuje.
Jedním z poznámek o systému typů rozhraní .NET Framework je, že i když struktury, výčty a primitivní typy (s výjimkou String) jsou typy hodnot, všechny dědí z referenčních typů. Struktury a primitivní typy dědí z referenčního typu System.ValueType, který dědí z Object. Výčtové typy dědí z referenčního typu System.Enum, který dědí z System.ValueType.
Typy hodnot, které mohou být null
U typů hodnot lze modifikátor přidat do názvu typu, ? který představuje verzi tohoto typu s možnou hodnotou null .
NullableTypeName
: NonArrayTypeName '?'
;
NullableNameModifier
: '?'
;
Typ hodnoty s možnou hodnotou null může obsahovat stejné hodnoty jako verze typu, která není nullable, a také hodnotu null. Proto pro typ hodnoty s možnou hodnotou null přiřazování Nothing proměnné typu nastaví hodnotu proměnné na hodnotu null, nikoli nulovou hodnotu typu hodnoty. Například:
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)
Proměnnou lze také deklarovat jako typ hodnoty null, a to tak, že do názvu proměnné vložíte modifikátor typu s možnou hodnotou null. Pro přehlednost není platný modifikátor typu s možnou hodnotou null u názvu proměnné i názvu typu ve stejné deklaraci. Vzhledem k tomu, že typy s možnou hodnotou null jsou implementovány pomocí typu System.Nullable(Of T), typ T? je synonymem pro typ System.Nullable(Of T)a dva názvy lze zaměnitelně.
? Modifikátor nelze umístit na typ, který je již nullable, a proto není možné deklarovat typ Integer?? nebo System.Nullable(Of Integer)?.
Typ T? hodnoty s možnou hodnotou null má členy System.Nullable(Of T) a také všechny operátory nebo převody zvednuty ze základního typu T do typu T?. Zvedání operátorů a převodů ze základního typu se ve většině případů nahrazují typy hodnot s možnou hodnotou null pro typy hodnot, které nemají hodnotu null. To umožňuje mnoho stejných převodů a operací, které platí i pro T použití T? .
Implementace rozhraní
Deklarace struktury a třídy mohou deklarovat, že implementují sadu typů rozhraní prostřednictvím jedné nebo více Implements klauzulí.
TypeImplementsClause
: 'Implements' TypeImplements StatementTerminator
;
TypeImplements
: NonArrayTypeName ( Comma NonArrayTypeName )*
;
Všechny typy zadané v Implements klauzuli musí být rozhraní a typ musí implementovat všechny členy rozhraní. Například:
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
Typ, který implementuje rozhraní také implicitně implementuje všechna základní rozhraní rozhraní. To platí i v případě, že typ explicitně nevypisuje všechna základní rozhraní v klauzuli Implements . V tomto příkladu TextBox struktura implementuje obě IControl a ITextBox.
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
Deklarování, že typ implementuje rozhraní a sám o sobě nehlásí nic v prostoru deklarace typu. Proto je platné implementovat dvě rozhraní s metodou se stejným názvem.
Typy nemohou implementovat parametr typu samostatně, i když může zahrnovat parametry typu, které jsou v oboru.
Class C1(Of V)
Implements V ' Error, can't implement type parameter directly
Implements IEnumerable(Of V) ' OK, not directly implementing
...
End Class
Obecná rozhraní lze implementovat vícekrát pomocí různých argumentů typu. Obecný typ však nemůže implementovat obecné rozhraní pomocí parametru typu, pokud zadaný parametr typu (bez ohledu na omezení typu) by se mohl překrývat s jinou implementací tohoto rozhraní. Například:
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
Primitivní typy
Primitivní typy jsou identifikovány prostřednictvím klíčových slov, což jsou aliasy pro předdefinované typy v System oboru názvů. Primitivní typ je zcela nerozlišitelný od typu, který aliasy: zápis rezervovaného slova Byte je úplně stejný jako psaní System.Byte. Primitivní typy se také označují jako vnitřní typy.
PrimitiveTypeName
: NumericTypeName
| 'Boolean'
| 'Date'
| 'Char'
| 'String'
;
NumericTypeName
: IntegralTypeName
| FloatingPointTypeName
| 'Decimal'
;
IntegralTypeName
: 'Byte' | 'SByte' | 'UShort' | 'Short' | 'UInteger'
| 'Integer' | 'ULong' | 'Long'
;
FloatingPointTypeName
: 'Single' | 'Double'
;
Vzhledem k tomu, že primitivní typ aliasy běžného typu, má každý primitivní typ členy. Má například Integer členy deklarované v System.Int32. Literály lze považovat za instance odpovídajících typů.
Primitivní typy se liší od jiných typů struktury v tom, že umožňují určité další operace:
Primitivní typy umožňují vytváření hodnot zápisem literálů. Jedná se například
123Io literál typuInteger.Je možné deklarovat konstanty primitivních typů.
Pokud jsou operandy výrazu všechny primitivní konstanty typu, je možné, aby kompilátor vyhodnocoval výraz v době kompilace. Takový výraz se označuje jako konstantní výraz.
Visual Basic definuje následující primitivní typy:
Celočíselné typy
Bytehodnot (1 bajtové celé číslo bez znaménka),SByte(1 bajtové celé číslo),UShort(2 bajtové celé číslo bez znaménka),Short(2 bajtovéUIntegercelé číslo), (4 bajtové celé číslo bez znaménka),Integer(4 bajtové celé číslo),ULong(8 bajtové celé číslo bez znaménka) aLong(8 bajtové celé číslo se znaménkem). Tyto typy se mapují naSystem.Byte, ,System.UInt32System.Int16System.UInt16System.Int32System.SByte,System.UInt64aSystem.Int64, v uvedeném pořadí. Výchozí hodnota celočíselného typu je ekvivalentní literálu0.Typy hodnotsch
Single(4bajtů s plovoucí desetinou čárkou) aDouble(8 bajtů s plovoucí desetinou čárkou) Tyto typy se mapují naSystem.SingleaSystem.Doublev uvedeném pořadí. Výchozí hodnota typu s plovoucí desetinou čárkou je ekvivalentní literálu0.Typ
Decimal(desetinná hodnota 16 bajtů), která se mapuje naSystem.Decimal. Výchozí hodnota desetinné čárky je ekvivalentní literálu0D.Typ
Booleanhodnoty, který představuje hodnotu pravdy, obvykle výsledek relační nebo logické operace. Literál je typuSystem.Boolean. Výchozí hodnotaBooleantypu je ekvivalentní literáluFalse.Typ
Datehodnoty, který představuje datum nebo čas a mapuje se naSystem.DateTime. Výchozí hodnotaDatetypu je ekvivalentní literálu# 01/01/0001 12:00:00AM #.Typ
Charhodnoty, který představuje jeden znak Unicode a mapuje naSystem.Char. Výchozí hodnotaChartypu je ekvivalentní konstantnímu výrazuChrW(0).Typ
Stringodkazu, který představuje posloupnost znaků Unicode a mapuje naSystem.String. Výchozí hodnotaStringtypu je hodnota null.
Výčty
Výčty jsou typy hodnot, které dědí z System.Enum a symbolicky představují sadu hodnot jednoho z primitivních integrálních typů.
EnumDeclaration
: Attributes? TypeModifier* 'Enum' Identifier
( 'As' NonArrayTypeName )? StatementTerminator
EnumMemberDeclaration+
'End' 'Enum' StatementTerminator
;
Pro typ Evýčtu je výchozí hodnota hodnota vytvořená výrazem CType(0, E).
Základní typ výčtu musí být celočíselný typ, který může představovat všechny hodnoty výčtu definované v výčtu. Je-li zadán základní typ, musí být , , , , , , Integer, , ULong, Longnebo jeden z jejich odpovídajících typů v System oboru názvů. UIntegerShortUShortSByteByte Pokud není explicitně zadán žádný podkladový typ, je výchozí Integerhodnota .
Následující příklad deklaruje výčet s základním typem Long:
Enum Color As Long
Red
Green
Blue
End Enum
Vývojář se může rozhodnout použít základní typ Long, jako v příkladu, povolit použití hodnot, které jsou v rozsahu Long, ale ne v rozsahu Integer, nebo zachovat tuto možnost pro budoucnost.
Členy výčtu
Členy výčtu jsou výčtové hodnoty deklarované v výčtu a členy zděděné z třídy System.Enum.
Rozsah členu výčtu je tělo deklarace výčtu. To znamená, že mimo deklaraci výčtu musí být člen výčtu vždy kvalifikovaný (pokud typ není speciálně importován do oboru názvů prostřednictvím importu oboru názvů).
Pořadí deklarací pro deklarace členů výčtu je významné, pokud jsou vynechány hodnoty konstantního výrazu. Členy výčtu mají implicitně Public přístup pouze. U deklarací členů výčtu nejsou povoleny žádné modifikátory přístupu.
EnumMemberDeclaration
: Attributes? Identifier ( Equals ConstantExpression )? StatementTerminator
;
Hodnoty výčtu
Výčtové hodnoty v seznamu členů výčtu jsou deklarovány jako konstanty zadané jako základní typ výčtu a mohou se objevit všude, kde jsou požadovány konstanty. Definice člena výčtu s = dává přidruženému členu hodnotu označenou konstantním výrazem. Konstantní výraz musí být vyhodnocen jako celočíselný typ, který se implicitně konvertibilní na základní typ a musí být v rozsahu hodnot, které mohou být reprezentovány základním typem. Následující příklad je v chybě, protože konstantní hodnoty 1.5, 2.3a 3.3 nejsou implicitně konvertibilní na základní celočíselný typ Long s striktní sémantikou.
Option Strict On
Enum Color As Long
Red = 1.5
Green = 2.3
Blue = 3.3
End Enum
Více členů výčtu může sdílet stejnou přidruženou hodnotu, jak je znázorněno níže:
Enum Color
Red
Green
Blue
Max = Blue
End Enum
Příklad ukazuje výčet, který má dva členy výčtu – Blue a Max -, které mají stejnou přidruženou hodnotu.
Pokud první definice hodnoty enumerátoru ve výčtu nemá žádný inicializátor, hodnota odpovídající konstanty je 0. Definice hodnoty výčtu bez inicializátoru poskytuje výčtu hodnotu získanou zvýšením hodnoty předchozího výčtu o 1hodnotu . Tato zvýšená hodnota musí být v rozsahu hodnot, které mohou být reprezentovány základním typem.
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
Výše uvedený příklad zobrazí hodnoty výčtu a jejich přidružené hodnoty. Výstup je:
Red = 0
Green = 10
Blue = 11
Důvody hodnot jsou následující:
Hodnota
Redvýčtu je automaticky přiřazena hodnotu0(protože nemá žádný inicializátor a je prvním členem hodnoty výčtu).Hodnota
Greenvýčtu je explicitně uvedena hodnota10.Hodnota
Bluevýčtu se automaticky přiřadí hodnotě větší než hodnota výčtu, která před ní textově předchází.
Konstantní výraz nemusí přímo nebo nepřímo používat hodnotu vlastní přidružené hodnoty výčtu (to znamená, že cykličnost ve výrazu konstanty není povolena). Následující příklad je neplatný, protože deklarace A a B jsou cyklické.
Enum Circular
A = B
B
End Enum
A závisí na B explicitně a B závisí na A implicitně.
Vyučování
Třída je datová struktura, která může obsahovat datové členy (konstanty, proměnné a události), členy funkce (metody, vlastnosti, indexery, operátory a konstruktory) a vnořené typy. Třídy jsou odkazové typy.
ClassDeclaration
: Attributes? ClassModifier* 'Class' Identifier TypeParameterList? StatementTerminator
ClassBase?
TypeImplementsClause*
ClassMemberDeclaration*
'End' 'Class' StatementTerminator
;
ClassModifier
: TypeModifier
| 'MustInherit'
| 'NotInheritable'
| 'Partial'
;
Následující příklad ukazuje třídu, která obsahuje každý druh člena:
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
Následující příklad ukazuje použití těchto členů:
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
Existují dva modifikátory MustInherit specifické pro třídu a NotInheritable. Není platné je zadat oba.
Základní specifikace třídy
Deklarace třídy může obsahovat specifikaci základního typu, která definuje přímý základní typ třídy.
ClassBase
: 'Inherits' NonArrayTypeName StatementTerminator
;
Pokud deklarace třídy nemá žádný explicitní základní typ, přímý základní typ je implicitně Object. Například:
Class Base
End Class
Class Derived
Inherits Base
End Class
Základní typy nemohou být parametrem typu samostatně, i když mohou zahrnovat parametry typu, které jsou v oboru.
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
Třídy mohou být odvozeny pouze z Object tříd a tříd. Třída je neplatná pro odvození od System.ValueType, System.Enum, System.ArraySystem.MulticastDelegate nebo System.Delegate. Obecná třída nemůže odvozovat nebo System.Attribute od třídy, která je z ní odvozena.
Každá třída má přesně jednu přímou základní třídu a cykličnost odvození je zakázána. Není možné odvodit z NotInheritable třídy a doména přístupnosti základní třídy musí být stejná jako nebo nadmnožina domény přístupnosti samotné třídy.
Členové třídy
Členy třídy se skládají z členů zavedených deklaracemi členů třídy a členy zděděné z jeho přímé základní třídy.
ClassMemberDeclaration
: NonModuleDeclaration
| EventMemberDeclaration
| VariableMemberDeclaration
| ConstantMemberDeclaration
| MethodMemberDeclaration
| PropertyMemberDeclaration
| ConstructorMemberDeclaration
| OperatorDeclaration
;
Deklarace člena třídy může mít Public, ProtectedFriend, , Protected Friend, nebo Private přístup. Pokud deklarace člena třídy neobsahuje modifikátor přístupu, deklarace se ve výchozím nastavení použije pro Public přístup, pokud se nejedná o deklaraci proměnné. V takovém případě je výchozí pro Private přístup.
Obor člena třídy je tělo třídy, ve kterém dojde k deklaraci členu, plus seznam omezení této třídy (pokud je obecný a má omezení). Pokud má Friend člen přístup, jeho obor se vztahuje na tělo třídy jakékoli odvozené třídy ve stejném programu nebo jakékoli sestavení, které byl udělen Friend přístup, a pokud člen má Public, Protectednebo Protected Friend přístup, jeho rozsah rozšiřuje na tělo třídy jakékoli odvozené třídy v libovolném programu.
Struktury
Struktury jsou typy hodnot, které dědí z System.ValueType. Struktury jsou podobné třídám, které představují datové struktury, které mohou obsahovat datové členy a členy funkce. Na rozdíl od tříd však struktury nevyžadují přidělení haldy.
StructureDeclaration
: Attributes? StructureModifier* 'Structure' Identifier
TypeParameterList? StatementTerminator
TypeImplementsClause*
StructMemberDeclaration*
'End' 'Structure' StatementTerminator
;
StructureModifier
: TypeModifier
| 'Partial'
;
V případě tříd je možné, aby dvě proměnné odkazovaly na stejný objekt, a proto operace s jednou proměnnou ovlivnit objekt odkazovaný druhou proměnnou. U struktur mají proměnné vlastní kopii jinýchShared než dat, takže není možné, aby operace na jedné z nich ovlivnily druhý, jak ukazuje následující příklad:
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
Při výše uvedené deklaraci následující kód vypíše hodnotu 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
Přiřazení a k b vytvoří kopii hodnoty, a b proto není ovlivněno přiřazením k a.x. Kdyby byl Point místo toho deklarován jako třída, výstup by byl 100 , protože a a b by odkazovaly na stejný objekt.
Členy struktury
Členy struktury jsou členy zavedené deklaracemi členů struktury a členy zděděné z System.ValueType.
StructMemberDeclaration
: NonModuleDeclaration
| VariableMemberDeclaration
| ConstantMemberDeclaration
| EventMemberDeclaration
| MethodMemberDeclaration
| PropertyMemberDeclaration
| ConstructorMemberDeclaration
| OperatorDeclaration
;
Každá struktura implicitně má Public konstruktor instance bez parametrů, který vytváří výchozí hodnotu struktury. V důsledku toho není možné deklaraci typu struktury deklarovat konstruktor instance bez parametrů. Typ struktury však umožňuje deklarovat parametrizované konstruktory instance, jako v následujícím příkladu:
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
Vzhledem k výše uvedené deklaraci vytvoří následující příkazy jak s, tak y inicializovaným x na nuluPoint.
Dim p1 As Point = New Point()
Dim p2 As Point = New Point(0, 0)
Vzhledem k tomu, že struktury přímo obsahují hodnoty polí (nikoli odkazy na tyto hodnoty), nemohou struktury obsahovat pole, která přímo nebo nepřímo odkazují. Například následující kód není platný:
Structure S1
Dim f1 As S2
End Structure
Structure S2
' This would require S1 to contain itself.
Dim f1 As S1
End Structure
Za normálních okolností může mít Publicdeklarace člena struktury pouze , Friendnebo Private přístup, ale při přepsání členů zděděných z Objecta ProtectedProtected Friend přístup lze použít také. Pokud deklarace člena struktury neobsahuje modifikátor přístupu, deklarace je výchozí pro Public přístup. Obor členu deklarovaného strukturou je tělo struktury, ve kterém se deklarace vyskytuje, a omezení této struktury (pokud byla obecná a měla omezení).
Standardní moduly
Standardní modul je typ, jehož členy jsou implicitně Shared a vymezeny na prostor deklarace standardního modulu obsahujícího obor názvů, nikoli pouze na samotnou deklaraci standardního modulu. Standardní moduly nemusí být nikdy vytvořena instance. Jedná se o chybu deklarování proměnné standardního typu modulu.
ModuleDeclaration
: Attributes? TypeModifier* 'Module' Identifier StatementTerminator
ModuleMemberDeclaration*
'End' 'Module' StatementTerminator
;
Člen standardního modulu má dva plně kvalifikované názvy, jeden bez standardního názvu modulu a jeden se standardním názvem modulu. Více než jeden standardní modul v oboru názvů může definovat člen s konkrétním názvem; nekvalifikované odkazy na název mimo některý z modulů jsou nejednoznačné. Například:
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
Modul může být deklarován pouze v oboru názvů a nemusí být vnořen v jiném typu. Standardní moduly nemusí implementovat rozhraní, implicitně jsou odvozeny od Objecta mají pouze Shared konstruktory.
Standardní členy modulu
Členy standardního modulu jsou členy představené jeho deklaracemi členů a členy zděděné z Object. Standardní moduly mohou mít jakýkoli typ členu s výjimkou konstruktorů instancí. Všechny standardní členy typu modulu jsou implicitně Shared.
ModuleMemberDeclaration
: NonModuleDeclaration
| VariableMemberDeclaration
| ConstantMemberDeclaration
| EventMemberDeclaration
| MethodMemberDeclaration
| PropertyMemberDeclaration
| ConstructorMemberDeclaration
;
Za normálních okolností může mít Publicstandardní deklarace členu modulu pouze , Friendnebo Private přístup, ale při přepsání členů zděděných z Object, Protected modifikátory přístupu a Protected Friend modifikátory přístupu mohou být zadány. Pokud standardní deklarace člena modulu neobsahuje modifikátor přístupu, deklarace se ve výchozím nastavení použije pro Public přístup, pokud se nejedná o proměnnou, která má výchozí Private přístup.
Jak jsme už uvedli, obor standardního člena modulu je deklarace obsahující standardní deklaraci modulu. Členové zdědění z Object tohoto speciálního oboru nejsou zahrnuti; tito členové nemají žádný obor a musí být vždy kvalifikovaní s názvem modulu. Pokud má Friend člen přístup, jeho obor se vztahuje pouze na členy oboru názvů deklarované ve stejném programu nebo sestaveních, které byly uděleny Friend .
Rozhraní
Rozhraní jsou odkazové typy, které jiné typy implementují, aby zajistily, že podporují určité metody. Rozhraní se nikdy nevytvořilo přímo a nemá žádnou skutečnou reprezentaci – jiné typy musí být převedeny na typ rozhraní. Rozhraní definuje kontrakt. Třída nebo struktura, která implementuje rozhraní, musí dodržovat svůj kontrakt.
InterfaceDeclaration
: Attributes? TypeModifier* 'Interface' Identifier
TypeParameterList? StatementTerminator
InterfaceBase*
InterfaceMemberDeclaration*
'End' 'Interface' StatementTerminator
;
Následující příklad ukazuje rozhraní, které obsahuje výchozí vlastnost Item, událost E, metodu Fa vlastnost P:
Interface IExample
Default Property Item(index As Integer) As String
Event E()
Sub F(value As Integer)
Property P() As String
End Interface
Rozhraní mohou využívat více dědičnosti. V následujícím příkladu rozhraní IComboBox dědí z obou ITextBox a 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
Třídy a struktury mohou implementovat více rozhraní. V následujícím příkladu je třída EditBox odvozena z třídy Control a implementuje obě IControl a 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
Dědičnost rozhraní
Základní rozhraní rozhraní jsou explicitní základní rozhraní a jejich základní rozhraní. Jinými slovy, množina základních rozhraní je úplné tranzitivní uzavření explicitních základních rozhraní, jejich explicitních základních rozhraní a tak dále. Pokud deklarace rozhraní nemá žádný explicitní základ rozhraní, neexistuje žádné základní rozhraní pro typ - rozhraní nedědí z Object (ačkoli mají rozšiřující převod na Object).
InterfaceBase
: 'Inherits' InterfaceBases StatementTerminator
;
InterfaceBases
: NonArrayTypeName ( Comma NonArrayTypeName )*
;
V následujícím příkladu jsou základní rozhraní IComboBox jsou IControl, ITextBoxa 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
Rozhraní dědí všechny členy jeho základních rozhraní. Jinými slovy, IComboBox výše uvedené rozhraní dědí členy SetText a SetItems také Paint.
Třída nebo struktura, která implementuje rozhraní také implicitně implementuje všechna základní rozhraní rozhraní.
Pokud se v přechodném uzavření základních rozhraní zobrazí více než jedno rozhraní, přispívá pouze jeho členy k odvozené rozhraní jednou. Typ, který implementuje odvozené rozhraní, musí implementovat pouze metody násobení definovaného základního rozhraní jednou. V následujícím příkladu Paint je nutné implementovat pouze jednou, i když třída implementuje IComboBox a 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
Klauzule Inherits nemá žádný vliv na jiné Inherits klauzule. V následujícím příkladu IDerived musí být kvalifikovat název s INestedIBase.
Interface IBase
Interface INested
Sub Nested()
End Interface
Sub Base()
End Interface
Interface IDerived
Inherits IBase, INested ' Error: Must specify IBase.INested.
End Interface
Doména přístupnosti základního rozhraní musí být stejná jako nebo nadmnožina domény přístupnosti samotného rozhraní.
Členy rozhraní
Členy rozhraní se skládají z členů zavedených jeho deklaracemi členů a členy zděděné ze základních rozhraní.
InterfaceMemberDeclaration
: NonModuleDeclaration
| InterfaceEventMemberDeclaration
| InterfaceMethodMemberDeclaration
| InterfacePropertyMemberDeclaration
;
I když rozhraní nedědí členy z Object, protože každá třída nebo struktura, která implementuje rozhraní dědí z Object, členy Object, včetně rozšiřujících metod, jsou považovány za členy rozhraní a lze volat na rozhraní přímo bez nutnosti přetypování na Object. Například:
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
Členové rozhraní se stejným názvem jako členové implicitně stínových ObjectObject členů. Členy rozhraní mohou být pouze vnořené typy, metody, vlastnosti a události. Metody a vlastnosti nemusí obsahovat tělo. Členy rozhraní jsou implicitně Public a nemusí určovat modifikátor přístupu. Obor člena deklarovaného v rozhraní je tělo rozhraní, ve kterém se deklarace vyskytuje, plus seznam omezení tohoto rozhraní (pokud je obecný a má omezení).
Pole
Matice je referenční typ, který obsahuje proměnné, ke kterým se přistupuje prostřednictvím indexů odpovídajících 1:1, s pořadím proměnných v poli. Proměnné obsažené v matici, označované také jako prvky pole, musí být všechny stejného typu a tento typ se nazývá typ prvku pole.
ArrayTypeName
: NonArrayTypeName ArrayTypeModifiers
;
ArrayTypeModifiers
: ArrayTypeModifier+
;
ArrayTypeModifier
: OpenParenthesis RankList? CloseParenthesis
;
RankList
: Comma*
;
ArrayNameModifier
: ArrayTypeModifiers
| ArraySizeInitializationModifier
;
Prvky pole přicházejí do existence při vytvoření instance pole a přestanou existovat, když je instance pole zničena. Každý prvek pole je inicializován na výchozí hodnotu jeho typu.
System.Array Typ je základním typem všech typů polí a nemusí být vytvořena instance. Každý typ pole dědí členy deklarované typem System.Array a je k němu konvertibilní (a Object). Jednorozměrný typ pole s prvkem T také implementuje rozhraní System.Collections.Generic.IList(Of T) a IReadOnlyList(Of T); pokud T je typ odkazu, pak typ pole také implementuje IList(Of U) a IReadOnlyList(Of U) pro všechny U , které mají rozšiřující odkaz převod z T.
Pole má pořadí , které určuje počet indexů přidružených k jednotlivým prvkům pole. Pořadí matice určuje počet dimenzí pole. Například pole s pořadím jednoho se nazývá jednorozměrné pole a pole s pořadím větší než jednorozměrné se nazývá multidimenzionální pole.
Následující příklad vytvoří jednorozměrné pole celočíselné hodnoty, inicializuje prvky pole a pak každý z nich vytiskne:
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
Program vypíše následující:
arr(0) = 0
arr(1) = 1
arr(2) = 4
arr(3) = 9
arr(4) = 16
arr(5) = 25
Každá dimenze pole má přidruženou délku. Délky dimenzí nejsou součástí typu pole, ale spíše jsou vytvořeny při vytvoření instance typu pole za běhu. Délka dimenze určuje platný rozsah indexů pro danou dimenzi: pro rozměr délky N, indexy mohou být v rozsahu od nuly do N-1. Pokud má dimenze nulovou délku, neexistují pro tuto dimenzi žádné platné indexy. Celkový počet prvků v matici je součin délky každé dimenze v matici. Pokud některá z dimenzí pole má délku nuly, znamená to, že matice je prázdná. Typ prvku pole může být libovolný typ.
Typy polí jsou určeny přidáním modifikátoru do existujícího názvu typu. Modifikátor se skládá z levé závorky, množiny nul nebo více čárk a pravé závorky. Změněný typ je typ prvku pole a počet dimenzí je počet čárek plus jedna. Pokud je zadán více než jeden modifikátor, je typ prvku pole pole pole. Modifikátory jsou čteny zleva doprava, přičemž nejkrajnější modifikátor je nejkrajnější pole. V příkladu
Module Test
Dim arr As Integer(,)(,,)()
End Module
typ arr prvku je dvojrozměrné pole třírozměrných polí jednorozměrných polí .Integer
Proměnnou lze také deklarovat jako typ pole tak, že do názvu proměnné umístíte modifikátor typu pole nebo modifikátor inicializace velikosti pole. V takovém případě je typ prvku pole typem zadaným v deklaraci a dimenze pole jsou určeny modifikátorem názvu proměnné. Pro přehlednost není platné mít modifikátor typu pole pro název proměnné i název typu ve stejné deklaraci.
Následující příklad ukazuje řadu místních deklarací proměnných, které jako typ elementu používají typy Integer polí:
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
Modifikátor názvu typu pole se rozšiřuje na všechny sady závorek, které následují. To znamená, že v situacích, kdy je za názvem typu povolena sada argumentů uzavřených v závorkách, není možné zadat argumenty pro název typu pole. Například:
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
V posledním případě (3) se interpretuje jako součást názvu typu, nikoli jako sada argumentů konstruktoru.
Delegáti
Delegát je referenční typ, který odkazuje na Shared metodu typu nebo na metodu instance objektu.
DelegateDeclaration
: Attributes? TypeModifier* 'Delegate' MethodSignature StatementTerminator
;
MethodSignature
: SubSignature
| FunctionSignature
;
Nejbližší ekvivalent delegáta v jiných jazycích je ukazatel funkce, ale zatímco ukazatel funkce může odkazovat pouze na funkce, delegát může odkazovat Shared na obě Shared metody i metody instance. V druhém případě delegát ukládá nejen odkaz na vstupní bod metody, ale také odkaz na instanci objektu, se kterou má vyvolat metodu.
Deklarace delegáta nemusí mít Handles klauzuli, Implements klauzuli, tělo metody nebo End konstruktor. Seznam parametrů deklarace delegáta nesmí obsahovat Optional ani ParamArray parametry. Doména přístupnosti návratového typu a typů parametrů musí být stejná jako nebo nadmnožina domény přístupnosti samotného delegáta.
Členové delegáta jsou členy zděděné z třídy System.Delegate. Delegát také definuje následující metody:
Konstruktor, který přebírá dva parametry, jeden typ
Objecta jeden typSystem.IntPtr.Metoda
Invoke, která má stejný podpis jako delegát.Metoda
BeginInvoke, jejíž podpis je podpis delegáta, se třemi rozdíly. Nejprve se návratový typ změní naSystem.IAsyncResult. Za druhé se na konec seznamu parametrů přidají dva další parametry: první typSystem.AsyncCallbacka druhý typObject. A nakonec se změní všechnyByRefparametry tak, abyByValbyly .Metoda
EndInvoke, jejíž návratový typ je stejný jako delegát. Parametry metody jsou pouze parametry delegáta, které jsouByRefpřesně parametry, ve stejném pořadí, v jakém se vyskytují v podpisu delegáta. Kromě těchto parametrů je na konci seznamu parametrů další parametr typuSystem.IAsyncResult.
Při definování a používání delegátů existují tři kroky: deklarace, vytvoření instance a vyvolání.
Delegáti se deklarují pomocí syntaxe deklarace delegáta. Následující příklad deklaruje delegáta, SimpleDelegate který nepřijímá žádné argumenty:
Delegate Sub SimpleDelegate()
Další příklad vytvoří SimpleDelegate instanci a okamžitě ji zavolá:
Module Test
Sub F()
System.Console.WriteLine("Test.F")
End Sub
Sub Main()
Dim d As SimpleDelegate = AddressOf F
d()
End Sub
End Module
Vytvoření instance delegáta pro metodu a následné okamžité volání prostřednictvím delegáta, protože by bylo jednodušší volat metodu přímo. Delegáti ukazují jejich užitečnost, když se používá anonymiza. Následující příklad ukazuje metodu MultiCallSimpleDelegate , která opakovaně volá instanci:
Sub MultiCall(d As SimpleDelegate, count As Integer)
Dim i As Integer
For i = 0 To count - 1
d()
Next i
End Sub
Není důležité pro metodu, MultiCall jaká je cílová metoda SimpleDelegate , jakou má tato metoda přístupnost, nebo jestli je Shared metoda nebo ne. Vše, co je důležité, je, že podpis cílové metody je kompatibilní s SimpleDelegate.
Částečné typy
Deklarace tříd a struktur mohou být částečné deklarace. Částečná deklarace může nebo nemusí plně popsat deklarovaný typ v rámci deklarace. Místo toho může být deklarace typu rozložena do více částečných deklarací v rámci programu; částečné typy nelze deklarovat přes hranice programu. Deklarace částečného Partial typu určuje modifikátor deklarace. Všechny další deklarace v programu pro typ se stejným plně kvalifikovaným názvem se sloučí společně s částečnou deklarací v době kompilace a vytvoří deklaraci jednoho typu. Například následující kód deklaruje jednu třídu Test se členy Test.C1 a 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
Při kombinování částečných deklarací typu musí mít Partial alespoň jedna z deklarací modifikátor, jinak výsledky chyb v době kompilace.
Poznámka. I když je možné zadat Partial pouze jednu deklaraci mezi mnoha částečnými deklaracemi, je lepší ji zadat pro všechny částečné deklarace. V situaci, kdy je jedna částečná deklarace viditelná, ale jedna nebo více částečných deklarací jsou skrytá (například případ rozšíření kódu generovaného nástrojem), je přijatelné ponechat Partial modifikátor mimo viditelnou deklaraci, ale zadat ji u skrytých deklarací.
Pouze třídy a struktury lze deklarovat pomocí částečných deklarací. Při porovnávání částečných deklarací se považuje zarit typu: dvě třídy se stejným názvem, ale různá čísla parametrů typu se nepovažují za částečné deklarace stejného času. Částečné deklarace mohou určovat atributy, modifikátory tříd, Inherits příkaz nebo Implements příkaz. V době kompilace jsou všechny části částečných deklarací sloučeny a použity jako součást deklarace typu. Pokud existují nějaké konflikty mezi atributy, modifikátory, základy, rozhraní nebo členy typu, výsledky chyb v době kompilace. Například:
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
Předchozí příklad deklaruje typ Test1 , který je Public, dědí z Object a implementuje System.IDisposable a System.IComparable. Částečné deklarace Test2 způsobí chybu v době kompilace, protože jedna z deklarací říká, že je Public a Test2 další říká, že Test2 je Private.
Částečné typy s parametry typu mohou deklarovat omezení a odchylku parametrů typu, ale omezení a odchylky od každé částečné deklarace se musí shodovat. Omezení a rozptyl jsou tedy speciální v tom, že se automaticky nezkombinují jako jiné modifikátory:
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
Skutečnost, že typ je deklarován pomocí více částečných deklarací, nemá vliv na pravidla vyhledávání názvů v rámci typu. V důsledku toho může částečná deklarace typu používat členy deklarované v jiných deklarací částečného typu nebo může implementovat metody v rozhraních deklarovaných v jiných deklarací částečného typu. Například:
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
Vnořené typy můžou mít také částečné deklarace. Například:
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
Inicializátory v rámci částečné deklarace budou stále prováděny v pořadí deklarace; Neexistuje však žádné zaručené pořadí provádění inicializátorů, ke kterým dochází v samostatných částečných deklaracích.
Vytvořené typy
Deklarace obecného typu sama o sobě neoznačí typ. Místo toho lze deklaraci obecného typu použít jako "podrobný plán" k vytvoření mnoha různých typů pomocí argumentů typu. Obecný typ s použitými argumenty typu se nazývá konstruovaný typ. Argumenty typu v konstruovaného typu musí vždy splňovat omezení na parametry typu, které odpovídají.
Název typu může identifikovat vytvořený typ, i když přímo nezadává parametry typu. K tomu může dojít v případě, že je typ vnořený v deklaraci obecné třídy a typ instance obsahující deklarace se implicitně používá pro vyhledávání názvů:
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
Konstruovaný typ C(Of T1,...,Tn) je přístupný, pokud jsou obecný typ a všechny argumenty typu přístupné. Pokud je například obecný typ CPublic a všechny argumenty T1,...,Tn typu jsou Public, pak vytvořený typ je Public. Pokud je Privatevšak název typu nebo jeden z argumentů typu, je přístupnost vytvořeného typu Private. Pokud je jeden typ argumentu vytvořeného typu Protected a jiný typ argument je Friend, pak je konstruovaný typ přístupný pouze ve třídě a jeho podtřídy v tomto sestavení nebo jakékoli sestavení, které byl udělen Friend přístup. Jinými slovy, doména přístupnosti pro konstruovaný typ je průnik domén přístupnosti jejích základních částí.
Poznámka. Skutečnost, že doména přístupnosti vytvořeného typu je průnikem jeho součástí, má zajímavý vedlejší účinek definování nové úrovně přístupnosti. Vytvořený typ, který obsahuje prvek, který je Protected a prvek, který je Friend přístupný pouze v kontextech, které mají přístup k oběmaFriendčlenůmProtected . Neexistuje však způsob, jak vyjádřit tuto úroveň přístupnosti v jazyce, protože přístupnost Protected Friend znamená, že k entitě lze přistupovat v kontextu, ke kterému má přístup buďFriendneboProtected členové.
Základní implementovaná rozhraní a členy konstruovaných typů jsou určeny nahrazením zadaných argumentů typu pro každý výskyt parametru typu v obecném typu.
Otevřené typy a uzavřené typy
Konstruovaný typ, pro kterého jeden nebo více argumentů typu jsou parametry typu obsahující typ nebo metoda se nazývá otevřený typ. Důvodem je to, že některé parametry typu typu stále nejsou známé, takže skutečný tvar typu ještě není plně známý. Naproti tomu obecný typ, jehož argumenty typu jsou všechny parametry bez typu, se nazývá uzavřený typ. Tvar uzavřeného typu je vždy plně známý. Například:
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
Vytvořený typ je otevřený typ Base(Of Integer, V) , protože ačkoli byl zadán parametr T typu, U byl zadán další parametr typu. Proto úplný tvar typu ještě není znám. Vytvořený typ je však uzavřený typ Derived(Of Double), protože byly zadány všechny parametry typu v hierarchii dědičnosti.
Otevřené typy jsou definovány takto:
Parametr typu je otevřený typ.
Typ pole je otevřený typ, pokud je jeho typ prvku otevřený typ.
Konstruovaný typ je otevřený typ, pokud jeden nebo více argumentů jeho typu je otevřený typ.
Uzavřený typ je typ, který není otevřeným typem.
Vzhledem k tomu, že vstupní bod programu nemůže být v obecném typu, budou uzavřeny všechny typy použité za běhu.
Speciální typy
Rozhraní .NET Framework obsahuje řadu tříd, které jsou zpracovávány speciálně rozhraním .NET Framework a jazykem Visual Basic:
Typ System.Void, který představuje typ void v rozhraní .NET Framework, lze přímo odkazovat pouze ve GetType výrazech.
Typy System.RuntimeArgumentHandleSystem.ArgIterator a System.TypedReference všechny můžou obsahovat ukazatele do zásobníku, takže se nemohou objevit v haldě rozhraní .NET Framework. Nelze je proto použít jako typy prvků pole, návratové typy, typy polí, obecné argumenty typu, typy s možnou hodnotou null, ByRef typy parametrů, typ hodnoty převedené na Object nebo System.ValueType, cíl volání členů Object instance nebo System.ValueTypenebo zvednut do uzavření.
Visual Basic language spec