2009-03-10 35 views
5

Ich habe eine Klasse namens Farben erstellt. Ich setze bestimmte Eigenschaften auf das Colors-Objekt und setze es in eine Session-Variable. Wenn ich auf die Session-Variable auf einer anderen Seite zugreife, bemerke ich, dass wenn ich unten Eigenschaften für objColors ändere, es die Session ändert und nicht die ursprünglichen Eigenschaften beibehält, was ich tun soll. Hier ein Beispiel:Wie erstellt man eine Kopie eines Objekts?

Session["Colors"] = Colors; 

Colors objColors = Session["Colors"]; 

//If I change objColors, it changes the Session. I don't want this to happen. 

Gibt es eine bessere Möglichkeit, die ursprünglichen Eigenschaften beizubehalten? Warum macht es das?

Antwort

7

Erstellen Sie einen Kopierkonstruktor für Farben. Dann tu das.

Kopieren Sie in Ihrem neuen Konstruktor einfach die Werte, die Sie benötigen, und machen Sie Ihre anderen Konstruktor-bezogenen Dinge.

Was im Code passiert, ist, dass Sie einen Zeiger auf ein Farben-Objekt bekommen. Session ["Colors"] und objColors verweisen auf dasselbe Objekt im Speicher. Wenn Sie also eines ändern, werden Änderungen in beiden widergespiegelt. Sie möchten ein brandneues Colors-Objekt, dessen Werte von objColors oder Session ["Colors"] initialisiert werden.

edit: Ein Copykonstruktor könnte wie folgt aussehen:

public Colors(Colors otherColors) 
{ 
    this.privateVar1 = otherColors.privateVar1; 
    this.publicVar2 = otherColors.publicVar2; 
    this.Init(); 
} 
+0

Können Sie genauer angeben, wie ein Kopierkonstruktor erstellt wird? – Xaisoft

+0

@Xaisoft ist es Ihre Aufgabe, die Logik für das Kopieren zu erstellen. Es geht darum, jeden Wert für das alte Objekt zu übernehmen und auf das neue Objekt anzuwenden. –

3

Sie können Ihre eigenen Klonierungsverfahren implementieren, um eine „Kopie“ eines Objekts zu machen. Der Grund dafür ist, dass die Zuweisung Colors objColors = Session["Colors"]; eine Referenzzuweisung ist, dies ist beabsichtigt. Alles, was Sie tun, ist einen lokalen Bereich Verweis auf ein Objekt, das bereits vorhanden ist. Werfen Sie einen Blick auf IClonable für das tatsächliche Klonen von Objekten. Dies ist nicht notwendig, Sie können auch eigene Kopiermethoden implementieren. Vielleicht möchten Sie auch einen Blick auf je nachdem, wie tief Ihr Objekt geht.

2

Der Zugriff auf das Objekt erfolgt über Referenz statt nach Wert. See here. Es gibt mehrere Möglichkeiten, dies zu ändern. Auf der Website finden Sie detaillierte Informationen.

3

Versuchen Sie einen Kopierkonstruktor.

Beispiel: link

1

Es gibt keine Art und Weise eingebaut und standardmäßig implementiert, aber Sie können diese erhalten, indem ICloneable Implementierung und MemberwiseClone aufrufen. Dies funktioniert nur für eine flache Kopie - wenn Ihr Objekt andere Objekte enthält, müssen Sie diese ebenfalls klonen. Eine einfache Implementierung wäre:

+0

Ist ICloneable nicht veraltet? – erikkallen

+0

@erikkallen: Nein. http://msdn.microsoft.com/en-us/library/system.icloneable.aspx –

1

Es tut dies, weil Sie nicht tatsächlich das Objekt kopieren, sondern einen Verweis auf das Objekt kopieren. Sie können eine tiefe Kopie in C# leicht tun Binary Serialisierung mit:

public static MemoryStream Serialize(object data) 
    { 

     MemoryStream streamMemory = new MemoryStream(); 
     BinaryFormatter formatter = new BinaryFormatter(); 
     formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; 

     formatter.Serialize(streamMemory, data); 

     return streamMemory; 


    } 



    public static Object Deserialize(MemoryStream stream) 
    { 

     BinaryFormatter formatter = new BinaryFormatter(); 
     formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; 
     return formatter.Deserialize(stream); 

    } 

Sie können diese beiden Methoden aufrufen, die zunächst ein Objekt nimmt und schreibt seine Daten an einen Memorystream. Dann können Sie Deserialize aufrufen, um eine neue Kopie eines Objekts basierend auf diesen Daten zu erhalten.

Eine letzte Sache, die Ihre Objekte serialisierbar sein müssen, tun dies, indem Sie das Serializable-Attribut auf jedes Objekt setzen.

0

Dies liegt daran, dass die Objekte objColors und Session ["Colors"] das gleiche Objekt sind.Wenn Sie eine Kopie speichern und das Original behalten möchten, müssen Sie Ihr Objekt klonbar machen.

Siehe folgend SO Q & A für einen Zeiger in der richtigen Richtung:

Deep cloning objects

2

Andere Antworten haben alle vorgeschlagen in einer oder anderen Weise zu klonen. Eine Alternative, die für Ihre spezielle Situation geeignet sein kann oder nicht, besteht darin, Ihren Typ unveränderlich zu machen. Operationen, die zuvor Ihren Typ mutiert haben, würden jetzt eine neue Instanz des Typs zurückgeben, Daten aus dem ursprünglichen Objekt übernehmen und die entsprechenden Änderungen vornehmen und die ursprüngliche Instanz intakt lassen. Dies ist der Ansatz, den die Klasse String zum Beispiel annimmt.

Sie müssen natürlich immer noch den entsprechenden Code schreiben, um die Daten innerhalb einer Instanz zu kopieren - aber der Code , der mit dem Typ arbeitet, könnte am Ende einfacher sein.

Dies mag in Ihrem Fall nicht angemessen sein, aber es ist eine Technik, zumindest zu berücksichtigen.

0

Da die Klasse Farben ist eine, die Sie erstellt haben, und ich nehme an, Sie ziemlich neu sind orientierte Programmierung zu widersprechen, können Sie eine Kopie construtor erstellen wie Stuart sagte mit etwas ähnlich der folgenden:

public class Colors 
{ 
    public int Property1; 
    public int Property2; 
    public int Property3; 
    public Colors() 
    { 
    //Do your regular constructor here 
    } 
    public Colors(Colors colorToCopy) 
    { 
    this.Property1 = colorToCopy.Property1; 
    this.Property2 = colorToCopy.Property2; 
    this.Property3 = colorToCopy.Property3; 
    } 
} 

Das Klonen über die Serialisierung ist eine allgemeinere Lösung und gewährleistet eine tiefe Kopie (das heißt, es kopiert die Eigenschaften ebenso wie die Eigenschaften von Eigenschaften), ist aber etwas schwieriger zu verstehen. Wenn bei dieser Lösung die Eigenschaften keine primitiven Datentypen sind, sind diese keine Kopien, es sei denn, Sie machen sie explizit als Kopien.

0

Wenn Sie eine Variable haben und ihr einen Sitzungswert zuweisen, erhalten Sie einen Zeiger auf beide.

Colors objColors = (Colors)Session["Colors"]; 

Session [ „Farben“] und objColors weisen auf das gleiche Objekt im Speicher, dann, wenn Sie in einem eine Änderung vorgenommen werden Änderungen in beide wieder.

Wenn Sie Unabhängigkeit wollen, müssen Sie eine Deep Copy von Ihnen Objekt. Sie müssen IClonable Schnittstelle für Rechnung und alle es ist verwandten Klassen implementieren:

public class Colors: IClonable 
{ 
    public int Red; 
    public int Green; 
    public int Blue; 

    public object Clone() 
    { 
    return this.MemberwiseClone(); 
    } 
} 

Jetzt haben Sie eine echte tiefe Kopie von Ihnen Rechnung Objekt.

Colors objColors = (Colors)((Colors)Session["Colors"]).Clone(); 

Weitere Informationen unter: Klonen von Objekten mit IClonable und MemberwiseClone je nachdem, wie tief Ihr Objekt geht.

Verwandte Themen