Die Klasse 'System.Array' ist die Basisklasse für alle Arrays in der Common Language Runtime. Sie enthält mehrere Überladungen der 'Copy'-Methode, durch die eine Anzahl von Elementen zwischen Instanzen der Array-Klasse kopiert werden kann - und zwar einschließlich 'Type-Casting' und 'Boxing'. Beim Kopieren ist es deshalb nicht notwendig, dass die Elemente des Quell-Array und des Ziel-Array vom gleichen Datentyp sind. Zulässige Erweiterungskonvertierungen sind möglich. Durch einen Aufruf kann beim Kopieren z.B. der Inhalt eines Short-Array in ein Long-Array oder die Elemente eines Integer-Array können in ein Double-Array eingetragen werden. Dieser Tipp bezieht sich auf die Überladung der 'Copy'-Methode, deren Parameterliste einen SourceIndex und einen DestinationIndex umfasst: Public Shared Sub Copy (sourceArray As Array, _ sourceIndex As Long, _ destinationArray As Array, _ destinationIndex As Long, _ length As Long) Bei einem eindimensionalen Array ist der Fall klar. Man muss nur darauf achten, dass das Quell-Array ab dem Startindex genügend Elemente umfasst (mindestens die Anzahl, die sich aus der Angabe im Length-Parameter ergibt). Und auch im Ziel-Array müssen genügend Elemente ab dem 'Destinationindex’ deklariert sein. (Die Methode verändert die Array-Deklarationen nicht; sie führt keine Anpassung des Zielarray durch, sondern löst ggf. eine Ausnahme aus.) Das Quell- und das Ziel-Array können identisch sein, die durch die Parameter angegebenen Array-Abschnitte dürfen sich sogar überlappen. Aber was ist bei mehrdimensionalen Arrays? Allerdings ist bei mehrdimensionalen Arrays zu beachten, dass der Rank (=die Zahl der Dimensionen) von Quell- und Ziel-Array identisch sein müssen. Es spielt jedoch keine Rolle, wie die Obergrenzen der einzelnen Dimensionen vereinbart worden sind. Die Copy-Methode berücksichtigt die mehrdimensionale Indizierung nicht, sondern kopiert einfach einen Abschnitt der Quell-Datenschlange in einen Abschnitt des Ziel-Array. (Die korrespondierenden Elemente des Quell- und Zielarray weisen deshalb nach dem Kopieren keine Entsprechung in der Indizierung auf - falls unterschiedliche Deklarations-Obergrenzen vorliegen. Zu einer 'Ausnahme'führt dieser Fall nicht!) Die unten angegebene Methode 'Get1DArrayIndex' ermittelt zu einem Array und einem Satz Indices, die sich auf ein Array-Element beziehen, den für 'Copy' benötigten Index in der Datenschlange. Es müssen so viele (gültige) Indizes angegeben werden (ParamArray) wie das Array Dimensionen aufweist. Falls die Routine scheitert, gibt sie den Wert -1 zurück. Die Methode ArrayCopyTo erwartet ein Quell-Array und ein Ziel-Array, die Angabe der Zahl der zu kopierenden Elemente und einen Satz Indices, aus denen der Startindex im QUELL-Array für den Kopier-Vorgang berechnet wird. Quell- und Ziel-Array müssen sich in den Datentypen entsprechen (Erweiterungskonvertierung Quelle -> Ziel) und die gleiche Zahl von Dimensionen aufweisen. Die Elemente werden im Zielarray ab Position 0 angeordnet. Die Methode ArrayCopyFrom erwartet ein Quell-Array und ein Ziel-Array, die Angabe der Zahl der zu kopierenden Elemente und einen Satz Indices, aus denen der Startindex im ZIEL-Array für den Kopier-Vorgang berechnet wird. Quell- und Zielarray müssen sich in den Datentypen entsprechen (Erweiterungskonvertierung Quelle -> Ziel) und die gleiche Zahl von Dimensionen aufweisen. Die Elemente werden aus dem Quellarray ab Position 0 kopiert. Falls das Kopieren scheitert, geben diese Funktionen 'false' zurück. Die Arrays werden von den Funktionen als 'System.Array' erwartet. Aus diesem Grund können Arrays beliebiger Dimensionszahl und beliebiger Datentypen übergeben werden. Allerdings darf 'Option Strict On' nicht eingestellt worden sein. Wer das nicht möchte, sollte jeweils eine Überladung für die erforderliche Zahl von Dimensionen und die verwendeten Datentypen programmieren. In der Test-Routine 'TestArrayCopy' wird zunächst ein vierdimensionales Array so mit Werten gefüllt, dass eine Identifikation der Array-Indices aus dem Array-Inhalt möglich ist. In einer Testschleife wird jeweils ein zufällig ausgewähltes Arrayelement in ein ein-elementiges (aber vier-dimensionales) Zielarray kopiert (ArrayCopyTo) und danach an die quell-entsprechende Position in einem zweiten Ziel-Array weitergereicht (ArrayCopyFrom). Dabei wird zugleich eine Datentyp-Konvertierung durchgeführt. Im dritten Schleifen-Block wird demonstriert, wie sich der eindimensionale Array-Index aus der Array-Indizierung ergibt. Hinweis für VB6-Umsteiger: ''' <summary> ''' Kopiert Arrayelemente ab Startindizierung in Zielarray ''' (ab Startposition 0) ''' </summary> ''' <param name="qarr">Quell-Array</param> ''' <param name="zarr">Ziel-Array</param> ''' <param name="ElementZahl">Anzahl der zu kopierenden ''' Array-Elemente</param> ''' <param name="StartIndices">Indizes des ersten zu kopierenden ''' Elements im Quell-Array</param> ''' <returns>True, falls erfolgreich</returns> Public Function ArrayCopyTo(ByVal qarr As System.Array, _ ByRef zarr As System.Array, _ ByVal ElementZahl As Integer, _ ByVal ParamArray StartIndices() As Integer) As Boolean ' Das Zielarray wird 'ByRef' übergeben und ist als ' System.Array deklariert (wie Quelle), damit Arrays ' beliebiger Dimensionen und beliebiger Datentypen ' übergeben werden können ' ---> 'Option Strict Off' ist leider erforderlich ' Enthalten die Array-Parameter Nullverweise? If IsNothing(qarr) Or IsNothing(zarr) Then Return False ' Stimmt die Dimensionszahl Quelle/Ziel überein? If qarr.Rank <> zarr.Rank Then Return False ' 1D-Index zur StartIndizierung (Quelle) ermitteln Dim StartIndex As Long = Get1DArrayIndex(qarr, StartIndices) ' Index ermittelt ? If StartIndex < 0 Then Return False ' Ausreichende Zahl von Elementen im Zielarray?? If zarr.Length < ElementZahl Then Return False Try ' Kopiervorgang durchführen Array.Copy(qarr, StartIndex, zarr, 0, ElementZahl) Return True Catch ex As Exception ' z.B. falls zu wenige (Rest-) Elemente im Quell-Array ' oder falls die Datentypen nicht zusammenpassen Return False End Try End Function ''' <summary> ''' Kopiert Arrayelemente ab 0 in Zielarray (gemäß ''' Start-Indizierung) ''' </summary> ''' <param name="qarr">Quell-Array</param> ''' <param name="zarr">Ziel-Array</param> ''' <param name="ElementZahl">Anzahl der zu kopierenden ''' Array-Elemente</param> ''' <param name="StartIndices">Indizes des ersten zu ''' kopierenden Elements im Ziel-Array</param> ''' <returns>True, falls erfolgreich</returns> Public Function ArrayCopyFrom(ByVal qarr As System.Array, _ ByRef zarr As System.Array, _ ByVal ElementZahl As Integer, _ ByVal ParamArray StartIndices() As Integer) As Boolean ' Stimmt die Dimensionszahl Quelle/Ziel überein? If qarr.Rank <> zarr.Rank Then Return False ' 1D-Index zur gegebenen Start-Indizierung (Ziel) ermitteln Dim StartIndex As Long = Get1DArrayIndex(zarr, StartIndices) ' 1D-Start-Index ermittelt ? If StartIndex < 0 Then Return False ' Ausreichende Zahl von Elementen im Quellarray?? If qarr.Length < ElementZahl Then Return False Try ' Kopiervorgang durchführen Array.Copy(qarr, 0, zarr, StartIndex, ElementZahl) Return True Catch ' z.B. falls zu wenige (Rest-) Elemente im Ziel-Array ' oder bei inkompatiblen Datentypen Return False End Try End Function Private Function Get1DArrayIndex(ByVal arr As System.Array, _ ByVal ParamArray StartIndices() As Integer) As Long ' Die Funktion ermittelt zu einem beliebig dimensionierten ' System.Array und der gegebenen Indizierung eines Elements ' den korrespondierenden 1D-Index in der 'Datenschlange' ' Falls die Indizierung nicht stimmt, wird -1 zurückgegeben Dim i, k As Integer ' Loops Dim ind As Long ' Rückgabe Dim fak() As Long ' Dim-Faktoren ' Zahl der übergebenen Indices = Rank des QuallArray ?? If UBound(StartIndices) + 1 <> arr.Rank Then Return -1 ' Gültige Indizierung? For i = 0 To UBound(StartIndices) If StartIndices(i) < 0 Or _ StartIndices(i) > UBound(arr, i + 1) Then Return -1 Next ReDim fak(arr.Rank) ' Berechnung des entsprechenden 1D-Start-Index für den ' Aufruf der Array.Copy-Methode ' Zu überspringende Elementzahl pro Indexwert einer Dimension ' => Multiplikation der Elementzahl aller höheren Dimensionen For i = 0 To arr.Rank - 1 fak(i) = 1 For k = i + 1 To arr.Rank - 1 fak(i) *= arr.GetLength(k) Next k Next i ' Berechnung des 1D-Startindex unter Verwendung ' der Index-Multiplikatoren ind = 0 For i = 0 To arr.Rank - 1 ind += fak(i) * (StartIndices(i)) Next i ' 1D-Index zurückgeben Return ind End Function Private Sub Test_ArrayCopy() Dim i, k, l, m As Integer ' Schleifen-Indizes Dim ind, zz As Integer ' für Demos Dim qarr(9, 19, 29, 39) As Integer ' Quell-Array Dim zarr1(0, 0, 0, 0) As Integer ' Ziel-Array für 1 Element Dim zarr2(9, 19, 29, 39) As Double ' Ziel-Array ' Vierdimensionales Array mit Daten füllen, aus deren ' Wert sich die zugehörigen Array-Indices ermitteln lassen For i = 0 To UBound(qarr, 1) For k = 0 To UBound(qarr, 2) For l = 0 To UBound(qarr, 3) For m = 0 To UBound(qarr, 4) ' Array mit Werten füllen, die verraten, ' welche Indizierung das Element ursprünglich ' besitzt qarr(i, k, l, m) = _ i * 10000000 + k * 100000 + l * 1000 + m Next m Next l Next k Next i ' 10000 Kopier-Testdurchläufe For zz = 1 To 10000 ' zufällige Indizierung i = CInt(Rnd() * UBound(qarr, 1)) k = CInt(Rnd() * UBound(qarr, 2)) l = CInt(Rnd() * UBound(qarr, 3)) m = CInt(Rnd() * UBound(qarr, 4)) ' Ein Array-Element in das Zielarray (1) kopieren If Not ArrayCopyTo(qarr, zarr1, 1, i, k, l, m) Then Stop ' Ist das angeforderte Element korrekt kopiert worden? If zarr1(0, 0, 0, 0) <> _ i * 10000000 + k * 100000 + l * 1000 + m Then Stop ' Ein Array-Element in das Zielarray (2) an die ' Indizierte Stelle kopieren If Not ArrayCopyFrom(zarr1, zarr2, 1, i, k, l, m) Then Stop 'Steht das kopierte Element im Zielarray an der ' korrekten Stelle? (Vergleich mit Quell-Array-Element) If zarr2(i, k, l, m) <> qarr(i, k, l, m) Then Stop zarr2(i, k, l, m) = 0 ' Zielarray wieder 'säubern' Next zz ' Demonstration, wie die Arrayelemente als 'Datenschlange' ' angeordnet sind (die höchste Dimension läuft zuerst) zz = -1 For i = 0 To UBound(qarr, 1) For k = 0 To UBound(qarr, 2) For l = 0 To UBound(qarr, 3) For m = 0 To UBound(qarr, 4) ' 1D-Index zur Indizierung besorgen ind = Get1DArrayIndex(qarr, i, k, l, m) ' Zählvariable hochsetzen zz += 1 ' Der 1D-Index läuft mit der Zählvariable hoch If ind <> zz Then Stop Next m Next l Next k Next i End Sub Dieser Tipp wurde bereits 13.733 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 (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. |
sevZIP40 Pro DLL Zippen und Unzippen wie die Profis! Mit nur wenigen Zeilen Code statten Sie Ihre Anwendungen ab sofort mit schnellen Zip- und Unzip-Funktionen aus. Hierbei lassen sich entweder einzelnen Dateien oder auch gesamte Ordner zippen bzw. entpacken. 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. |