2009-03-25 6 views
5

Was ist der beste Weg zu tief einen verbundenen Satz von Objekten zu klonen? Beispiel:Wie tiefverbundene Objekte in C# geklont werden?

class A { 
    B theB; // optional 
    // ... 
} 

class B { 
    A theA; // optional 
    // ... 
} 

class Container { 
    A[] a; 
    B[] b; 
} 

Die offensichtliche Sache zu tun ist, die Gegenstände zu gehen und klonen alles tief, wie ich dazu komme. Dies erzeugt jedoch ein Problem - wenn ich eine A kloniere, die eine B enthält, und diese B ebenfalls in der Container ist, wird diese B zweimal geklont, nachdem ich die Container geklont habe.

Der nächste logische Schritt ist ein Dictionary erstellen und jedes Objekt nachschlagen, bevor ich es klonen. Dies scheint jedoch eine langsame und ungeeignete Lösung zu sein.

Irgendwelche Gedanken?

+0

hier ist, wie ich es mache: http://valueinjecter.codeplex.com/wikipage?title=Deep%20Cloning&referringTitle=Home – Omu

Antwort

2

Es ist sicherlich keine elegante Lösung, aber es ist nicht ungewöhnlich, ein Wörterbuch (oder Hashmaps) zu verwenden. Einer der Vorteile ist, dass eine Hashmap eine konstante Nachschlagezeit hat, so dass die Geschwindigkeit hier nicht wirklich leidet.

2

Die von Ihnen vorgeschlagene Wörterbuchlösung ist die beste, die ich kenne. Um weiter zu optimieren, könnten Sie object.GetHashCode() verwenden, um einen Hash für das Objekt zu erhalten und dieses als Wörterbuchschlüssel zu verwenden. Sollte schnell sein, es sei denn, Sie sprechen über riesige Objektbäume (10 bis 100 Tausende von Objekten).

2

Nicht, dass ich mit C# vertraut bin, aber normalerweise erfordert jede Art von Crawling eines Graphen für irgendeine Art von Verarbeitung eine Nachschlagetabelle, um die Verarbeitung eines Objekts aufgrund von zyklischen Referenzen zu stoppen. Also würde ich denken, dass Sie das hier genauso machen müssen.

0

vielleicht ein Bit-Flag erstellen, um anzuzeigen, ob dieses Objekt zuvor geklont wurde.

0

Eine andere mögliche Lösung, die Sie untersuchen könnten, besteht darin, die Objekte in einem Stream zu serialisieren und sie dann aus demselben Stream in neue Instanzen zu rekonstruieren. Dies wirkt oft Wunder, wenn alles andere schrecklich verschlungen und unordentlich erscheint.

Marc

+0

Können Sie das näher erläutern? Wie kann ich verhindern, dass dasselbe Objekt zweimal serialisiert wird? Oder, wenn ich nur "Container" serialisiere, wie könnte ich * Referenzen * auf A und B statt auf das gesamte Objekt speichern, um Doppelungen zu vermeiden? Ich kann nicht einfach einen einfachen Index verwenden, wie Sie es von dem einfachen Beispiel glauben würden. – zildjohn01

+0

WCF unterstützt dies mit einigen Optimierungen (http://blogs.msdn.com/sowmy/archive/2006/03/26/561188.aspx). Aber die Serialisierung wird, obwohl sie schnell zu programmieren ist, viel schlechter abschneiden als eine explizite tiefe Kopie. –

+0

True - Serialisierung und Deserialisierung sind in Bezug auf die Leistung möglicherweise nicht die besten Ergebnisse. Das kommt auf das ewige "Es kommt drauf" -Szenario an :-) Brauchen Sie Top-Leistung und machen Sie das hunderttausende Male in einer Schleife -> dann ist Serialisierung vielleicht nicht der beste Weg. –