vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#

https://www.vbarchiv.net
Rubrik: Variablen/Strings   |   VB-Versionen: VB2005, VB200823.04.08
Inferentielle Deklaration von Variablen

OPTION INFER ON erlaubt strikte Deklaration von lokalen Variablen ohne As Klausel !!

Autor:   Manfred BohnBewertung:  Views:  12.901 
ohne HomepageSystem:  WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

In VB 2008 ist es möglich, lokale, nicht-statische Variablen inferentiell zu deklarieren, d.h. es ist nicht erforderlich, durch Verwendung einer AS-Klausel bei der Deklaration den Datentyp festzulegen, sondern dies kann auch durch Zuweisung eines beliebigen Ausdrucks erfolgen.

Die Deklaration...

Dim x = 10

...würde in VB2005 bei der Einstellung OPTION STRICT ON zu einer Fehlermeldung führen und bei OPTION STRICT OFF käme es zu einer Deklaration, die 'AS Object' entspräche; das bedeutet, der Datentyp von 'x' würde - wenig effizient - erst zur Laufzeit temporär aufgrund von Wertzuweisungen festgelegt.

Die neue inferentielle Deklaration, möglich bei OPTION INFER ON, führt dazu, dass 'x' als Integer deklariert wird - und zwar bereits beim Kompilieren (=frühe Bindung). Die IDE-Intellisense zeigt in diesem Fall die Variable 'x' als Integer an.

Weshalb wird 'x' ausgerechnet als Integer inferentiell deklariert?
Weshalb nicht als Byte, Short oder Long.
Denkbar wären auch die unsigned-Varianten der integrierten Ganzzahl-Datentypen.

Das liegt daran, dass VB intern auf ein umfangreiches Regelsystem zurückgreift, durch das stets eindeutig festgelegt ist, welchen Werttyp ein bestimmter Ausdruck im Ergebnis liefert. Und dieses Regelsystem bestimmt für den nicht näher spezifizierten Wert 10 den Datentyp INTEGER. Die inferentielle Deklaration gilt deshalb auch als eine STRIKTE Deklaration.

Nicht unproblematisch!
Selbst bei Verwendung von OPTION STRICT ON läßt sich dem Quellcode nicht direkt entnehmen, welchen Datentyp eine inferentiell deklarierte Variable besitzt. Man muss auf die von der Entwicklungsumgebung (Intellisense) gelieferte Information zurückgreifen.

Noch ein Beispiel:

Dim aa, bb As Short
aa = 4 : bb = 2
 
Dim c1 As Short = aa \ bb ' Diese Zuweisung ist möglich
Dim c2 As Short = aa / bb ' STRICT ON verbietet diese Zuweisung
Dim c3 = aa / bb ' INFER ON erlaubt Deklaration u. Zuweisung

Umgehen kann man das nur, indem man es sich zur Angewohnheit macht, bei inferentieller Deklaration prinzipiell eine Konvertierungsfunktion zu verwenden. Die Gefahr von Flüchtigkeitsfehlern ist sonst nicht zu unterschätzen. Der Quellcode liefert in diesem Fall die Dokumentation des deklarierten Datentyps.

Im Beispiel könnte man eine Short-Variable inferentiell so deklarieren:

Dim c4 = CShort(aa / bb) ' INFER ON erlaubt Deklaration u. Zuweisung

Man muss wissen, dass die inferentielle Deklaration als IDE-Voreinstellung in VB 2008 (für neue Projekte) zugelassen wird. Um diese Einstellung zu ändern, kann man im Menü 'Tools' ---> 'Options' den Knoten 'Projects and Solutions' erweitern und in den 'VB-Defaults' OPTION INFER auf OFF stellen. (OPTION STRICT und OPTION EXPLICIT sollten auf ON eingestellt sein.) Möchte man später in einer Code-Datei die inferentielle Deklaration verwenden, braucht man lediglich am Dateianfang OPTION INFER ON einzufügen. Dieses Statement setzt die IDE-Voreinstellung für den Code in der Datei ausser Kraft.

In den folgenden Codezeilen habe ich - ohne Anspruch auf Vollständigkeit - eine Reihe von Beispielen für die inferentielle Variablen-Deklaration zusammengestellt, um zu demonstrieren, was geht und was dabei allerdings auch zu beachten ist.

Noch ein Hinweis:
(VB-Doku zum Thema 'Local Type Inference').
Type inference strongly types the variable instead of leaving it as Object. The compiler uses a variable's initializer to determine the variable's type at compile time to produce early-bound code

Es gibt aber Ausnahmen:

  • auch Variable des Typs Object können bei inferentieller Deklaration verwendet werden, dabei entsteht natürlich wieder eine Variable des Typs Object, für die späte Bindung gilt;
  • auch Verweisvariable für Objekt-Klone können inferentiell deklariert werden, unterliegen dann ebenfalls der späten Bindung.

''' <summary>
''' Demo-Beispiele für die inferentielle Deklaration
''' lokaler, nicht-statischer Variablen
''' </summary>
Public Sub Demo(ByVal ParamArray x() As Short)
 
  ' ==========================
  ' 1.) Integrierte Datentypen
  ' ==========================
 
  ' zwei Short-Konstanten
  Const Minimum As Short = 2
  Const Maximum As Short = 10
 
  ' Inferentielle Variablen-Deklaration
  ' (zulässig auch bei OPTION STRICT ON)
  ' Der Datentyp wird vom Ergebnistyp des Ausdrucks bestimmt
  Dim sum = Minimum + Maximum ' Short-Variable (=12)
  Dim Mitte1 = (Maximum + Minimum) / 2 ' Double-Variable (=6.0)
  Dim Mitte2 = (Maximum + Minimum) \ 2 ' Integer-Variable(=6)
 
  ' ... besser, man verwendet eine explizite Konvertierung
  ' Short-Variable (=6)
  Dim Mitte3 = CShort((Maximum + Minimum) \ 2)
 
  ' Die folgenden Zeilen sind bei OPTION STRICT OFF zulässig,
  ' weil sonst bei KONSTANTEN-Deklaration eine
  ' AS-Klausel verlangt wird.
  ' Const cMitte1 = (Maximum + Minimum) / 2 'Double-Konst(6.0)
  ' Const cMitte2 = (Maximum + Minimum) \ 2 'Integer-Konst(6)
  ' Short-Konstante (6)
  ' Const cMitte3 = CShort((Maximum + Minimum) \ 2)
 
  ' Inferentielle Deklaration von Double-Variablen
  ' (auch durch die integrierten IEEE-Sonderwerte möglich)
  Dim c = Double.PositiveInfinity
  Dim d = Double.NaN ' = not a number (z.B. 0 / 0 )
 
  ' Inferentielle Deklaration von Single-Variablen
  Dim s1 = Single.NegativeInfinity
  Dim s2 = CSng(Double.Epsilon)
 
  ' Formal zulässige Inferentielle Deklaration einer
  ' Integer-Variable, die allerdings einen Laufzeitfehler
  ' (Überlauf) auslösen würde
  ' Dim i1 = CInt(c)
 
  ' Strikte Deklaration
  ' (ebenfalls Laufzeitfehler - vom Typ 'Überlauf',
  ' obwohl bei NaN ('not a number') eigentlich eher ein
  ' Konvertierungsfehler zu erwarten wäre)
  ' Dim i2 As Integer = CInt(d)
 
  ' Inferentielle Deklaration einer Long-Variable (Int64)
  ' (der numerische Wert ist für eine Integer-Variable zu groß,
  ' deshalb wird automatisch eine Long-Variable deklariert)
  Dim l = 4294967296 ' (=2^32)
 
  ' Inferentielle Deklaration einer Double-Variable
  ' (weil das Exponent-Zeichen im Ergebnis einen Double liefert)
  Dim dbl1 = 2L ^ 32L
 
  ' Die IDE kann im folgenden Fall den Überlauf nicht erkennen,
  ' deklariert eine Long-Variable.
  ' Zur Laufzeit gäbe das einen Fehler.
  ' Dim l2 = l * l
 
  ' Gleitkomma-Werte deklarieren stets eine Double-Variable
  ' nie DECIMAL oder SINGLE ....
  Dim dbl2 = 1.0E+20
 
  ' ... es sei denn, der Wert verfügt über eine Typ-Kennung
  ' (Das Ausrufezeichen ist das Kürzel für Single-Precision)
  Dim sng = -1.0E+20! ' --> Single-Variable
  ' Typ-Kennungen gibt es auch bei Ganzzahl-Variablen
  Dim ulng = 100UL ' --> ULONG-Variable
 
  ' Entsprechende Deklarations-Fehler werden zwar erkannt ....
  ' Dim sh = 40000S '--> Überlauf-Fehler
  ' Dim sg = 1E100! '--> Überlauf-Fehler
 
  ' ... aber nicht immer auch als Fehler behandelt
  Dim dec = -100UL ' --> Decimal (weil negativ !!)
  Dim itg = -100US ' --> Integer (weil negativ !!)
  Dim lng = -100UI ' --> Long (weil negativ !!)
  ' Bei unsachgemäßer inferentieller Deklaration
  ' wird demzufolge automatisch derjenige SIGNED-Datentyp
  ' herangezogen, der die gesamte Werte-Spannweite des
  ' eigentlich angeforderten UNSIGNED-Typs aufnehmen kann
 
 
  ' VB 2008 erkennt die folgenden sechs Datentyp-IDs:
  ' (bei Variablen und Konstanten)
  ' % --> Integer '& --> Long
  ' ! --> Single '# --> Double
  ' @ --> Decimal '$ --> String
 
  ' VB 2008 erkennt zehn Datentyp-IDs bei Literalen:
  ' (einige stammen aus C++)
  '  I --> Integer L --> Long S --> Short
  ' UI --> UInteger UL --> ULong US --> UShort
  '  D --> Decimal
  '  F --> Single (Float) R --> Double (Real)
  '  C --> Char (z.B Dim x = "A"c --> Char, enthält "A")
 
  ' VB 2008 erkrennt zwei numerische Präfixe, die mit
  ' den obigen Ganzzahl-IDs kombiniert werden können
  ' &O --> Octalzahl &H --> Hexadecimalzahl
 
  ' Inferentielle Präfix-Deklarationen
  Dim oc1 = &O122US ' --> UShort (= 82)
  Dim oc2 = &O1772& ' --> Long (= 1018)
  Dim hx1 = &HFFFFL ' --> Long (= 65535)
  Dim hx2 = &HFFFFD ' --> Integer (D ist hier kein ID!!)
 
  ' Dim hx3 = &HFFFFR ' --> 'Gleitkomma-ID ist unzulässig
 
 
  ' Überladene Funktionen können unterschiedliche Datentypen
  ' inferentiell deklarieren (parameterabhängig)!
  Dim ab1 = Math.Abs(CSng(-1.5)) ' -> Single Variable
  Dim ab2 = Math.Abs(-1.5) ' -> Double-Variable
  Dim ab3 = Math.Abs(-1) ' -> Integer-Variable
  Dim ab4 = Math.Abs(CByte(1.5)) ' -> Int16-Variable (Short!)
 
 
  ' ==========
  ' 2.) Arrays
  ' ==========
 
  ' Inferentielle Deklaration eines Short-Arrays
  ' der Länge x.Length (=abhängig vom rufenden Code)
  Dim a = x
 
  If a.Length >= 4 Then
    ' Inferentielle Deklaration einer Short-Variable
    ' gültig innerhalb eines Code-Blocks
    Dim b = a(3)
  End If
 
  ' Diese inferentielle Deklaration erstellt kein Array,
  ' sondern eine einfache Integer-Variable
  Dim arr1 = New Integer()
  ' ReDim arr1(20) --> nicht möglich, weil kein Array
 
  ' Inferentielle Erstellung eines 'leeren' 2-dim-Arrays
  ' durch Verwendung geschweifter Klammern
  Dim arr2 = New Integer(,) {}
  ReDim arr2(20, 4) ' Vereinbarung der Elemente des Array
 
  ' Als inferentielle Deklaration fungiert auch folgendes
  ' Statement, weil dabei ebenfalls die AS-Klausel weg-
  ' gelassen worden ist
  Dim SomeShorts = New Short() {4, 18, 11, 9, 8, 0, 5}
 
  ' Die Deklaration der Schleifen-Kontrollvariable 'Number'
  ' erfolgt inferentiell. (Bei Option Infer Off und
  ' Option Strict Off muss zusätzlich Option Explicit Off
  ' gesetzt werden, um die implizite Deklaration von Number
  ' als 'Object' zu erzwingen)
  Sum = 0
  For Each Number In SomeShorts
    sum += number
  Next Number
 
 
  ' ===========
  ' 3.) Objekte
  ' ===========
 
  ' Inferentielle Deklaration einer Objekt-Variable, deren
  ' Datentyp erst zur Laufzeit aufgrund einer Zuweisung
  ' festgelegt wird
  Dim nt = Nothing
 
  ' Die Variable 'o' wird trotz der Wertzuweisung erst zur
  ' Laufzeit temporär als Datentyp 'Single' eingerichtet, weil
  ' sie OBJECT ist
  Dim o As Object = CSng(1)
 
  ' Inferentielle Deklaration
  ' (Die Variable 't' wird im Codemodus als 'Object',
  ' im Debug-Modus als 'Single' [=zugewiesener Werttyp]
  ' behandelt;
  ' ebenfalls sog. späte Bindung)
  Dim t = o
 
  ' Die Variable 'str' bekommt deshalb zur Laufzeit
  ' den ID-String 'System.Single' zugewiesen
  Dim str = t.GetType.ToString()
 
  ' Zuweisung eines Double-Wertes zu 't'
  t = d
  ' Auf die Variable 'str' wird jetzt der String 'System.Double'
  ' zugewiesen
  Str = t.GetType.ToString()
 
 
  ' Erstellung einer Objekt-Instanz
  ' (Da es sich bei 'btn' um eine lokale Variable handelt,
  ' ist das 'WithEvents'-Statement nicht zugelassen.)
  Dim btn As New Windows.Forms.Button
 
  ' Die inferentielle Deklaration einer Variable klappt auch
  ' bei Verwendung einer Objekt-Eigenschaft
  btn.Text = "Schaun mer mal"
  Dim strng = btn.Text ' --> String-Variable
 
  ' Inferentielle Deklaration einer Objektvariable,
  ' die einen Verweis auf btn enthält
  Dim btn2 = btn
 
  ' Auch für Objekte, die in anderen Objekten enthalten sind,
  ' kann per inferentieller Deklaration eine Verweisvariable
  ' erstellt werden
  Dim fo = btn.Font
 
  ' Die folgende Deklaration ist nur bei INFER ON zugelassen,
  ' bzw. bei STRICT OFF - es handelt sich dennoch um SPÄTE
  ' BINDUNG,
  ' d.h. die Variable 'FoC' wird erst zur Laufzeit als FONT
  ' deklariert und der Objekt-Clone als Font-Kopie erstellt
  Dim FoC = btn.Font.Clone
 
End Sub



Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
 
Copyright ©2000-2024 vb@rchiv Dieter OtterAlle Rechte vorbehalten.


Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.