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

https://www.vbarchiv.net
Rubrik: Variablen/Strings · Arrays   |   VB-Versionen: VB628.06.05
Übergabe eines Array an eine Prozedur: ByVal

ByVal-Übergabe eines Array an eine Prozedur durch einen Variant-Parameter

Autor:   Manfred BohnBewertung:  Views:  36.828 
ohne HomepageSystem:  Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11kein Beispielprojekt 

Übergibt man eine Variable an eine 'Function' oder 'Sub' mit dem Schlüsselwort 'ByRef' wird ein Verweis auf die Variable übergeben. Die Änderung der Variable innerhalb der Prozedur wirkt sich auch auf die Variable im rufenden Programm aus.

Verwendet man statt dessen das Schlüsselwort 'ByVal', wird intern eine Kopie der Variable erstellt, auf die die Prozedur zugreifen kann. Veränderungen des Wertes der Variable innerhalb der Prozedur wirken sich auf das 'Original' im rufenden Programm nicht aus.

Versucht man ein ARRAY mit dem Schlüsselwort 'ByVal' zu übergeben, meldet die VB-IDE sofort einen Fehler: Array-Argument muss als Verweis 'ByRef' übergeben werden.

DAS IST EIN BLUFF !!

Verwendet man statt dessen einen Variant-Parameter mit dem Schlüsselwort 'ByVal' in der Deklarationszeile der 'Function' bzw. 'Sub', kann man auch ein Array 'ByVal' an diesen Parameter übergeben. Es wird eine lokale Kopie des gesamten Array zur Verwendung in der gerufenen Routine erstellt.

Zu beachten ist allerdings, dass ein Variant-Parameter alles mögliche enthalten kann. Man sollte sich deshalb innerhalb der Prozedur stets zunächst davon überzeugen, dass tatsächlich ein Array übergeben worden ist und aus welchem Datentyp die Elemente dieses Array bestehen.
Von Interesse ist ferner, dass dieses lokale Array sich stets wie ein dynamisch deklariertes Array verhält - unabhängig von der Art der Deklaration im rufenden Programm. Der Datentyp des lokalen Array entspricht dem Datentyp, mit dem es im rufenden Programm deklariert worden ist. Das gilt auch für Anzahl und Grenzen der Dimensionen.

Die Übergabe eines Array an eine Prozedur durch einen Variant-Parameter funktioniert bei allen internen VB-Datentypen, ausser bei Strings fester Länge. Bei Arrays, deren Elemente benutzerdefinierte Datentypen sind, muss die COM-Unterstützung vorhanden sein. (Zur Erzeugung solcher UDTs siehe Tipp:  UDT als Parameter einer Klassen-Prozedur II).

' =====================================================================
' Demonstration der Übergabe eines Array
' an eine Prozedur 'ByVal'
' =====================================================================
Option Explicit
 
' schnelle API-Kopierfunktion für Bytefolgen
Private Declare Sub CopyMemory Lib "kernel32" _
  Alias "RtlMoveMemory" ( _
  Ziel As Any, _
  Quelle As Any, _
  ByVal Anzahl_Bytes As Long)
 
' Teil des 'SafeArray', ...
Private Type udtSafeArray
  Dimensionen As Integer     ' Zahl der Dimensionen
  Features As Integer        ' Attribute (Bitfolge)
  Bytes_Pro_Feld As Long     ' Anzahl der Bytes pro Element
  Locks As Long              ' Anzahl der gesetzten Array-Sperren
  Data_Pointer As Long       ' bei Strings: Varptr --> Deskriptor
End Type
Sub main()
  ' statisches Integer Array deklarieren
  Dim iarr(1 To 100, 1 To 10) As Integer
 
  Dim i As Long, k As Long                 ' Loop
 
  ' Array mit Werten füllen
  For i = 1 To 100
    For k = 1 To 10
      iarr(i, k) = i * 100 + k
    Next k
  Next i
 
  ' Aufruf einer Funktion (BYVAL-Parameter)
  Test1 iarr()
 
  ' Ist das Array tatsächlich unverändert geblieben?
  For i = 1 To 100
    For k = 1 To 10
      If iarr(i, k) <> i * 100 + k Then Stop ' Nanu!
    Next k
  Next i
 
  ' Aufruf einer Funktion (BYVAL-Parameter)
  Test2 iarr()
 
  ' Ist das Array tatsächlich unverändert geblieben?
  For i = 1 To 100
    For k = 1 To 10
      If iarr(i, k) <> i * 100 + k Then Stop ' Nanu!
    Next k
  Next i  
End Sub
Private Function Test1(ByVal iarr As Variant) As Boolean
  ' Die Routine demonstriert die Ermittlung der
  ' Informationen zu einem Array, das ByVal durch
  ' einen Variant-Parameter übergeben worden ist
 
  Dim i As Long, k As Long   ' Loop
  Dim typname As String      ' Datentyp des Array
  Dim vt As VbVarType        ' VarType der Elemente des Array
  Dim sa As udtSafeArray     ' Variable für SafeArray-Struktur
  Dim ptr As Long            ' Zeiger auf SafeArray-Struktur
 
  ' Liegt überhaupt ein Array in 'iArr' vor
  If Not IsArray(iarr) Then Exit Function
 
  ' Datentyp der Array-Elemente feststellen
  typname = TypeName(iarr)
  If UCase(typname) <> "INTEGER()" Then Stop ' NANU
 
  ' Vartype der Elemente des Array ermitteln
  vt = VarType(iarr) - vbArray
  If Not vt = vbInteger Then Stop ' NANU
 
  ' Zeiger auf SafeArray-Struktur besorgen
  Call CopyMemory(ptr, ByVal VarPtr(iarr) + 8, 4&)
  Call CopyMemory(sa, ByVal ptr, LenB(sa))
 
  ' Es müssten 2 Dimensionen sein ....
  If sa.Dimensionen <> 2 Then Stop  ' Nanu
 
  ' Es müssten 2 Bytes/Feld sein (wg. Integer)
  If sa.Bytes_Pro_Feld <> 2 Then Stop  ' Nanu!
 
  ' Array-Inhalt prüfen und dann
  ' explizit zurücksetzen (nur lokal!)
  For i = LBound(iarr, 1) To UBound(iarr, 1)
    For k = LBound(iarr, 2) To UBound(iarr, 2)
       If iarr(i, k) <> i * 100 + k Then Stop ' Nanu!
       iarr(i, k) = 0
    Next k
  Next i
 
  ' Am Ende der Routine wird das lokale Array
  ' automatisch freigegeben
 
  Test1 = True
End Function
Private Function Test2(ByVal iarr As Variant) As Boolean
  ' Lokales (dynamisch deklariertes) Array
  ' übergeben 'BYVAL'
  ' innerhalb der Prozedur neu deklarieren
  ' nur 1 Dimension, andere Grenzen
 
  ' Das lokale Array ist dynamisch deklariert!!
  ReDim iarr(-100 To 100)
  Dim i As Long
 
  ' Lokales Array füllen
  For i = -100 To 100
    iarr(i) = i
  Next i
 
  ' Am Ende der Routine wird das lokale Array
  ' automatisch freigegeben
  Test2 = True
End Function



Anzeige

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

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.