Autor Beitrag
zenten
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Do 05.08.10 23:33 
Hallo..

Ich habe ein Verständnisproblem bei der Clone-Methode der Klasse ArrayList.

Die Methode Clone() gibt eine flache Kopie der ArrayList zurück.

Zur flachen Kopie sagt msdn folgendes:
"Bei einer flachen Kopie einer Auflistung werden nur die Elemente der Auflistung kopiert, unabhängig davon, ob sie Verweis- oder Werttypen sind. Die Objekte auf die verwiesen wird, werden jedoch nicht kopiert. Die Verweise in der neuen Auflistung zeigen auf dieselben Objekte wie die Verweise in der ursprünglichen Auflistung.
Im Gegensatz dazu werden bei einer tiefen Kopie zusätzlich die Elemente sowie alle untergeordneten Elemente kopiert, auf die direkt oder indirekt verwiesen wird."

Quelle: msdn.microsoft.com/d...ne%28v=VS.80%29.aspx

Das bedeutet doch eigentlich folgendes:

Beispiel:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
//ArrayList wird erstellt
ArrayList liste_1 = new ArrayList();

//Flache Kopie der liste_1
ArrayList liste_2 = (ArrayList)liste_1.Clone();

Wenn ich jetzt Werte in der liste_1 verändere, werden die Werte in der liste_2 nicht verändert,
wiederspricht das nicht aber einer "flachen Kopie"?

Danke
Gruß
zenten


Moderiert von user profile iconChristian S.: Topic aus C# - Die Sprache verschoben am Do 05.08.2010 um 23:46
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Do 05.08.10 23:46 
Hallo!

Nein, das widerspricht dem nicht. Die Thematik der flachen Kopie bezieht sich ja darauf, was mit den Elementen in der Auflistung passiert. Die Liste selber wird kopiert, sodass ein Zugriff auf liste_1 nicht auch auf liste_2 zugreift.

Dass eine flache Kopie erstellt wird, heißt, dass wenn liste_1 zum Zeitpunkt des Klonens Elemente enthält, die Referenzdatentypen sind, nur die Referenzen kopiert werden, diese aber dann weiterhin auf dieselben Objekte (Instanzen) zeigen, da diese nicht kopiert werden.

Übrigens ist ArrayList veraltet und stattdessen sollte List<T> benutzt werden ;-)

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
zenten Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Fr 06.08.10 00:33 
Aaaber,
wenn die kopierten Referenzen weiterhin auf die original Objekte verweisen, dann wird doch eine Änderung in der
Kopie durch den Verweis, wieder auf die original Objekte verwiesen und somit werden diese dann doch auch verändert?!
Es zeigen doch dann quasi zwei Verweise auf den gleichen Speicherbereich?!

Ich weiß, dass du recht hast, nur irgendwie verstehe ich das nicht, habe sonst eigentlich keine
Probleme mit Wert- und Referenztypen u.s.w..:(
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 06.08.10 00:47 
Hier mal ein kleines Beispiel:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
    class Example
    {
      public string Foo;
    }

    static void Main(string[] args)
    {
      var list1 = new ArrayList();

      var e = new Example();
      e.Foo = "blubb";

      list1.Add(e);

      var list2 = (ArrayList) list1.Clone();
      ((Example)list2[0]).Foo = "blah";

      Console.WriteLine(((Example)list1[0]).Foo);

      list2.Add(new Example());

      Console.WriteLine(list1.Count.ToString() + " " + list2.Count.ToString());
      Console.ReadLine();
    }

Das gibt bei mir
Zitat:
blah
1 2
aus, also zeigen die Einträge in beiden Listen auf das selbe Objekt, aber die beiden Listen sind nicht identisch!

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
zenten Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Fr 06.08.10 01:44 
Danke für das Beispiel!

Wenn ich aber folgenden Code verwende:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
        static void Main(string[] args)
        {
            var list1 = new ArrayList();

            list1.Add(1);

            var list2 = (ArrayList)list1.Clone();
            list2[0] = 2;


            Console.WriteLine(list1[0]);

        }

Wird eine "1" ausgegeben!
Obwohl doch alle Elemente der ArrayLIst als Object-Datentypen gespeichert werden
und damit also auch Referenztypen sind, hier wird der Wert in der Original Liste nicht verändert,
warum verhält es sich hier anders?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 06.08.10 10:09 
Ein Integer ist ein Wertetyp und kein Referenztyp. Wertetypen wie z.B. Integer werden bei Zuweisung kopiert, bei Referenztypen wie die Example Klasse von Christian wird eine weitere Referenz auf die selbe Instanz erzeugt. Du musst bei solchen Aktionen immer fein zwischen Wert- und Referenztypen unterscheiden.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 07.08.10 11:26 
Das bringt uns hier nicht weiter, da der int durch Boxing zu einem Referenztyp wird. Es gibt aber einen ganz anderen riesigen Unterschied zwischen den beiden Ausschnitten:
ausblenden C#-Quelltext
1:
((Example)list2[0]).Foo = "blah";					

ausblenden C#-Quelltext
1:
list2[0] = 2;					

Die erste Zeile ruft ein Objekt ab und manipuliert seine Daten - da das Objekt in beiden Listen steckt, ist der Effekt auch über beide Listen beobachtbar.
Die zweite Zeile ersetzt das Objekt an Index 0 durch das neue Objekt "2". Das juckt das alte Objekt in der alten Liste aber wenig.

Der Code würde sich also nur entsprechen, wenn wir die erste Zeile umformulieren:
ausblenden C#-Quelltext
1:
list2[0] = new Example { Foo = "blah" };					

Und schon haben wir den gleichen Effekt wie bei der int-Liste.

Zumindest in diesem Beispiel können wir nicht umgekehrt die zweite Zeile entsprechend der ersten umformulieren, da sich int-Objekte nicht manipulieren lassen. int ist immutable, eine 3 wird immer eine 3 bleiben. Das ist zwar eine entscheidende Eigenschaft jedes ordentlich konstruierten Structs, aber bei Klassen ist das genauso möglich. Allgemein verhalten sich immutable Structs und immutable Klassen in ihrem Verhalten exakt gleich. int könnte auch eine Klasse sein - man würde es höchstens an der Performance bemerken.

_________________
>λ=