Ü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. 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 Dieser Tipp wurde bereits 36.843 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
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. |
Neu! sevCommand 4.0 Professionelle Schaltflächen im modernen Design! Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Tipp des Monats April 2024 Skyfloy Chart von Microsoft und dazu noch gratis Tutorial für Microsoft Chart Controls für Microsoft .NET Framework 3.5 TOP Entwickler-Paket TOP-Preis!! Mit der Developer CD erhalten Sie insgesamt 24 Entwickler- komponenten und Windows-DLLs. Die Einzelkomponenten haben einen Gesamtwert von 1605.50 EUR... |
||||||||||||||||
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. |