2016-12-09 3 views
0

Ich habe zwei Sammlungen - collection1 und collection2eine Sammlung Klonen

collection1 hat eine Reihe von Klassenobjekten in ihr und ich versuche collection2 mit Kopien der gleichen Objekte mit dem folgenden Befehl zu füllen:

Set collection2 = collection1 

Dies gibt mir nicht das gewünschte Ergebnis, obwohl, weil, wenn ich

collection2.Remove 1  

verwenden es t entfernt Er Objekt bei Index 1 von beide Sammlungen.

Unten finden Sie den vollständigen Code, die ich hoffte, würde die Ausgabe 10 Objekte in collection1, nachdem der Code unten versucht, ein von collection2

Sub test() 
    Dim collection1 As Collection 
    Dim collection2 As Collection 
    Dim testObj As Worksheet 
    Dim i As Integer 

    Set collection1 = New Collection 
    Set collection2 = New Collection 

    For i = 1 To 10 
     collection1.Add testObj 
    Next i 

    Set collection2 = collection1 
    collection2.Remove 1 
    Debug.Print collection1.Count 
End Sub 


ich zu entfernen und es funktioniert, aber ich bin auf der Suche sowohl Füllung zu vermeiden Sammlungen eins nach dem anderen, wenn möglich:

... 
For i = 1 To 10 
    collection1.Add testObj 
    collection2.Add testObj 
Next i 
... 

Der Grund, warum ich auf diese Option nicht so scharf darauf bin, ist, weil letztlich mehrere Sammlungen zu verwenden beabsichtige ich, manipulieren sie eine Ich nehme Kopien an verschiedenen Stellen, damit ich am Ende viele Loops in meinem Code habe, anstatt nur einen.

+0

Ich denke, Sie meinen 'Set collection2 = collection1' vielleicht ... – Rdster

+2

Es gibt keine Kopierfunktion für eine Sammlung. Dies: Set collection2 = collection2 macht nur einen zweiten Verweis auf das Collection-Objekt. Ihre beste Wette ist, was Sie vermeiden möchten, IE gleichzeitig zu füllen. – Sorceri

+0

@Rdster das war nur ein Tippfehler, korrigiert jetzt – CallumDA

Antwort

5

ich kopieren versuchen collection2 mit Kopien der gleichen Objekte zu füllen der Verwendung von folgender Befehl ein:

Set collection2 = collection1 

das ist noch nicht das, was dieser Befehl tut. Das Schlüsselwort Set "kopiert keine Objekte" und weiß nicht automatisch, dass es sich um ein Collection Objekt handelt, das Elemente enthält.

Das Set Schlüsselwort weist eine Referenz zu. Nicht mehr, nicht weniger.

Was Set collection2 = collection1 tut, ist, wörtlich:

Nehmen Sie den Zeiger für das collection1 Objekt und ersetzen was collection2 bezieht sich auf damit.

Das Set Anweisung wirksam wird Verwerfen des Objekts, das Sie in erster Linie erstellt, wenn Sie dies tat:

Set collection2 = New Collection 

Sie sind nicht „Kopieren von Objekten“ oder „Füllung collection2“ - Sie‘ wieder überschreiben seine Objektreferenz, wodurch collection2 Punkt auf die das gleiche Objekt als collection1.

Und da beiden Zeiger auf das gleiche Objekt zeigen ... ein Element zu entfernen entweder Collection in der Tat von „both“ Sammlungen entfernt es werden wird, ... denn es gibt nur eine beteiligt Sammelobjekt.


Das ObjPtr Stichwort helfen, etwas Licht auf, kann, was passiert, auch (ohne Papiere?):

Set collection1 = New Collection 
Debug.Print "collection1: " & ObjPtr(collection1) 

Set collection2 = New Collection 
Debug.Print "collection2: " & ObjPtr(collection2) 

'the debug output contains 2 different addresses at this point 

Set collection2 = collection1 
Debug.Print "collection1: " & ObjPtr(collection1) 
Debug.Print "collection2: " & ObjPtr(collection2) 

'now the debug output clearly shows that 
'both collection1 and collection2 are pointing to the same object 

Wenn Sie Kopien einer Sammlung benötigen, müssen Sie eine Funktion, die eine nimmt Sammlung und gibt ein ganz neues Objekt:

Public Function CopyCollection(ByVal source As Collection) As Collection 
    Dim result As New Collection 
    Dim item As Variant 
    For Each item In source 
     result.Add item 
    Next 
    Set CopyCollection = result 
End Function 

As already noted in comments aber th Dies funktioniert nur, wenn Ihre Sammlungen nicht verschlüsselt sind. Aufgrund der begrenzten Anzahl von Collection (die Schlüssel können nicht iteriert werden) müssen Sie stattdessen Scripting.Dictionary verwenden, wenn Sie eine verschlüsselte Sammlung klonen müssen.

1

Zuerst müssen Sie nicht Dim collection1 As Collection und Set collection1 = New Collection. Dies kann ersetzt werden durch Dim collection1 As New Collection

Nun, was Sie tun, macht die Sammlung2, um die Sammlung1 zu enthalten. Es ist so, als ob man eine Schachtel (collection1) mit einer Menge Kästen versieht und diese Schachtel dann in eine andere Schachtel (collection2) legt.

Die Alternative ist, entweder beide gleichzeitig zu füllen oder einen Code zu tun, den Inhalt wie

for i = 1 to collection1.count 
    collection2.add collection1.item(i) 
next i 
+2

http://www.cpearson.com/excel/classes.aspx empfiehlt nicht, Objekte automatisch zu instanziieren Würden Sie dem widersprechen? – CallumDA

+0

Die Erfahrung, die ich mit Sammlungen habe, ist mit meinem [Deck mischen] (http://codereview.stackexchange.com/questions/148546/deck-shuffle-and-drawing-cards) und es gab mir noch keine Probleme. – Moacir

+0

Auch der erste Teil der Antwort ist nicht das, wonach Sie gefragt haben, also fühlen Sie sich frei zu ignorieren. – Moacir