Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

Instanz wird durch Zuweisung nicht kopiert [Kopierkonstruktor, ICloneable, ...]
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

Instanz wird durch Zuweisung nicht kopiert [Kopierkonstruktor, ICloneable, ...]

beantworten | zitieren | melden

Da bei einem solchen befehl


myClass class = new myClass();
myClass y = class;
die beiden Instanzen "eine Instanz" sind wäre meine idee gewesen einen Konstruktor zu schreiben der alle variablen kopiert das würde dann so aussehen.

Konstruktor


public myClass(myClass oldClass)
{
    this.x = oldClass.x;
    .....
}

Aufruf


myClass y = new myClass(class);

warum funktioniert das trotzdem nicht (also wenn ich class.x ändere ändert sich auch y.x mit und umgekehrt)


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
m0rius
myCSharp.de - Member

Avatar #avatar-3125.png


Dabei seit:
Beiträge: 1043

beantworten | zitieren | melden

Hallo baensch,

du hast einen sogenannten Kopierkonstruktor implementiert. Wenn das von dir beschriebene Verhalten auftritt, ist das Feld oder die Eigenschaft x ein Referenztyp und kein Wertetyp – dessen Wert würde übernommen werden und würde sich bei einer Änderung nicht auf die andere Instanz auswirken. So teilen sich die Instanzen den Referenztyp – du hast in diesem Fall nur eine shallow copy, eine flache Kopie, erstellt.
Wenn du nicht-geteilte Referenztypen in den Instanzen verwenden willst, musst du eine deep copy, eine tiefe Kopie, durchführen.

m0rius
Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

Oh das hätte ich auch bemerken können.

Gibt es da auch eine Einfachere Lösung oder ist die einzige nur wertetypen zu kopieren?


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
Zicore
myCSharp.de - Member



Dabei seit:
Beiträge: 413

beantworten | zitieren | melden

Hallo baensch,

schau dir dazu auch mal das IClonable Interface an:

ICloneable-Schnittstelle

ggf. hier im Forum danach suchen.

André
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

Hallo,

wenn ich eine wirkliche Kopie eines Objectes brauche, serialisiere ich es in einen MemoryStream und deserialisiere es wieder. Bisher imho die wirksamste Methode (wenn auch nicht die performanteste).

grüße
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo zusammen,

wenn man Objekte kopieren möchte, ist das meistens ein Hinweis darauf, dass mit dem Design was nicht stimmt. Siehe Kopie ohne ICloneable.

herbivore
private Nachricht | Beiträge des Benutzers
rollerfreak2
myCSharp.de - Member

Avatar #avatar-3271.jpg


Dabei seit:
Beiträge: 928

beantworten | zitieren | melden

Zitat
wenn ich eine wirkliche Kopie eines Objectes brauche, serialisiere ich es in einen MemoryStream und deserialisiere es wieder
Das ist m.E. die wohl schlechteste Lösung. Das IClonable Interface ist doch genau für das Kopieren von Objekten da, und das Objekt selber sollte schon wissen welche referenz Member es neu instanziieren muss!
Again what learned...
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

@herbivore
Zitat
wenn man Objekte kopieren möchte, ist das meistens ein Hinweis darauf, dass mit dem Design was nicht stimmt.

Ich habe eine ObservableCollection mit einer selbst geschriebenen Klasse. Diese Klasse besteht aus einer ObservableCollection, die die Geometrie der Instanz beschreibt und eine Variable, die die Qualität der Instanz beschreibt.

Am Anfag ist das StartObjekt und das EndObjekt in der ObservableCollection. Ich berechne den Weg vom Start zum EndObjekt und füge die fehlenden Zwischenschritte ein.
(z.B. Anfang: StartObjekt.Qualität = 0; EndObjekt.Qualität = 3;
Ende(nach meiner Bearbeitung sollte die Collection so aussehen): StarObjekt.Qualität=0; Objekt1.Qualität = 1; Objekt2.Qualität = 2; EndObjekt.Qualität = 3;)

Hättest du vielleicht einen besseren Vorschlag für mein Problem, denn ich sehe keinen anderen Ausweg.


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

@unconnencted
Zitat
serialisiere ich es in einen MemoryStream und deserialisiere es wieder

kannst du mir sagen wie das konkret aussieht?
meinst du etwa mit XMLSerializer?


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
JunkyXL
myCSharp.de - Experte

Avatar #avatar-3234.gif


Dabei seit:
Beiträge: 1732
Herkunft: Ein paar Bytes südlich von string

beantworten | zitieren | melden

Er meint wahrscheinlich den BinaryFormatter (.Serialize()).
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

danke einmal ich werde die ICloneable Schnittstelle verwenden


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo baensch,
Zitat
Hättest du vielleicht einen besseren Vorschlag für mein Problem, denn ich sehe keinen anderen Ausweg.
ich sehe in deiner Beschreibung keine Stelle, an der Objekte kopiert werden müssen.

herbivore
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

Zitat
ich sehe in deiner Beschreibung keine Stelle, an der Objekte kopiert werden müssen

Doch das Objekt1 hat z.B.: genau die selbe Geometrie wie das StartObjekt.
Somit kopiere ich das StartObjekt und ändere nur die Qualität.

Was ist an Clonen so schlecht zieht man daraus irgend welche Nachteile?


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo baensch,

was am Kopieren von Objekten schlecht ist, habe ich ja in dem verlinkten Thread beschrieben.

Wobei es in deinem Fall so ist, dass du das zu kopierende Objekt quasi nur als Vorlage für ein echt neues Objekt verwendest. Also das Ganze ein bisschen in Richtung Prototyp (Entwurfsmuster) geht. So ein Vorgehen kann dann schon Sinn machen.

herbivore
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

Ok vielen dank


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
spike24
myCSharp.de - Member



Dabei seit:
Beiträge: 451
Herkunft: Steiermark Österreich

beantworten | zitieren | melden

Kann sein dass ich zu spät dran bin, aber:
soweit ich das verstanden habe sind in deinem "StartObjekt" Koordinaten eines Punktes drin.
Weiters ist auch die Qualität drin (was auch immer Qualität bedeutet)
Dein Problem ist dass Du einen Punkt (StartObjekt) mit verschiedenen Qualitäten brauchst.
was hältst Du davon wenn Qualität ein eigenes Object wird, initialisiert mit:

Qualität qualität = new Qualität(3);
und dass als Schlüssel in einem Dictionary benützt

dictionary.Add(qualität, startObjekt);
somit hättest Du jedem Punkt eine Qualität verpasst ohne dass Du Dein StartObjekt verändern muss (somit musst du es nicht mehr kopieren)
mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen
private Nachricht | Beiträge des Benutzers
baensch
myCSharp.de - Member



Dabei seit:
Beiträge: 135

Themenstarter:

beantworten | zitieren | melden

Danke spike24,
leider sind die Collection und die Qualität nur die beiden wichtigsten Variablen meiner Klasse somit ist die lösung mit einem Dictionary nicht möglich.


while(!asleep)
{
    sheep++;
}
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

Hmm, also als Abschluss vllt. noch einmal als Erklärung warum ich mich beim (nicht performance kritischen) clonen nicht auf IClonable verlasse..

a. bei großen Daten Objecten sagen wir 20 Propertys aufwärts wird die Clone Methode unübersichtlich, und wenn dann noch collections dabei kommen irgendwann unwartbar.

b. Ich arbeite mit mehreren Entwicklern zusammen, die auch an den erstellten Objecten arbeiten.. und wenns dann mal wieder schnell gehen muss, wird meistens :IClonable und Clone() übersehen, und einfach ein Property hinzugefügt, das dann beim clonen fehlt. (Ich will mich selber da nicht ausschliessen).

Klar wenns um performance geht, ist das natürlich grottig. Aber es läuft stabil und hat sich bewährt.

und wie JunkyXL schon sagte benutze ich tatsächlich den Binary Formatter bzw. den DataContractSerializer (Silverlight)

Grüße
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5989
Herkunft: Leipzig

beantworten | zitieren | melden

Zitat von unconnected
a. bei großen Daten Objecten sagen wir 20 Propertys aufwärts wird die Clone Methode unübersichtlich, und wenn dann noch collections dabei kommen irgendwann unwartbar.

Für diese Fälle gibt es doch die MemberwiseClone-Methode.
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

Kleiner ausschnitt aus der doku zu Memberwise Clone

Zitat
Die MemberwiseClone-Methode erstellt eine flache Kopie, indem ein neues Objekt erstellt wird und anschließend die nicht statischen Felder des aktuellen Objekts in das neue Objekt kopiert werden. Wenn ein Feld ein Werttyp ist, wird das Feld bitweise kopiert. Wenn es sich bei dem Feld um einen Verweistyp handelt, wird nicht das Objekt, auf das verwiesen wird, sondern der Verweis kopiert. Daher verweisen das ursprüngliche Objekt und der Klon auf dasselbe Objekt.

So eine flache Kopie kann man wirklich in den seltensten Fällen gebrauchen.
private Nachricht | Beiträge des Benutzers
Tarion
myCSharp.de - Member



Dabei seit:
Beiträge: 386

beantworten | zitieren | melden

Ich weiß, auch nicht die Beste Lösung, aber damals hab ich so etwas mal per Reflection gelößt. Ich hatte ein Objekt mit vielen Properties in einer Bibliothek und konnte es nicht ändern, wollte aber eine Kopie ohne jede Property einzeln kopieren zu müssen, da hat sie die Reflection (auch um an private member zu kommen) bewährt. Das konnte ich auch soweit steuern, dass ich einige nicht kopierbare Teile die auch ein BinaryFormatter nicht nimmt (Sockets und so...) manuell auslassen konnte.

Also im groben, mit Reflection ein Objekt auseinander und die Werte in nem neuen Objekt setzten. Alles von außen ohne das zu kopierende Objekt zu ändern.

Ansonsten kann man noch an bestimmten Stellen überlegen Structs zu benutzten. Hab mir dein Beispiel jetzt nicht genau genug angesehen um zu beurteilen ob es dir hilft.
private Nachricht | Beiträge des Benutzers