Autor Beitrag
ocram1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Fr 17.02.12 22:51 
Hallo,
Bin grad dabei das Buch "Visual C# 2010" durchzuarbeiten.

Zum Kapitel Arrays hätte ich folgende Verständnisfrage:
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:
25:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Projekt1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] Arr = new int[1]{5};          
            int[] newArr;
            newArr = Arr;
            Arr[0] = 6;
            Console.WriteLine(newArr[0]);
            
            int Var = 5;
            int newVar = Var;
            Var = 6;
            Console.WriteLine(newVar);
            Console.ReadLine();
        }
    }
}


Wie ersichtlich passiert folgendes:
Ich erstelle ein Array, kopiere dieses, ändere das ursprüngliche und gebe das neue aus.
Das selbe mache ich mit einer Variable.
Nun die Frage: Wieso wird das kopierte Array verändert wenn ich das ursprüngliche Array verändere?

Grüsse.

Moderiert von user profile iconTh69: Quote- durch C#-Tags ersetzt
ocram1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Fr 17.02.12 23:02 
Es wird im Buch wohl darauf hingewiesen das beide Arrays auf die selbe Adresse verweisen.
Meine Frage ist nun eigentlich wieso ist das so? Welchen Sinn hat es ein Array zu kopieren wenn ich im Endeffekt immer auf die selben Adressen zugreife?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 17.02.12 23:47 
Hallo ocram1 :welcome:

mittels newArr = Arr; erzeugst du kein neues Array, sondern newArr ist nun einfach eine weitere Referenz auf das vorhandene Array (welches schon durch die Variable Arr referenziert wird).
Bei Wertetypen (wie int, short, long oder auch Strukturen) wird dagegen immer eine Kopie angelegt, so daß eine Änderung des Originalwertes keinen Einfluß auf die Kopie hat.

Der Unterschied zwischen Referenz- und Wertetyp ist entscheidend für das Verständnis von C# (bzw. .NET).

Wenn du wirklich ein neues Array haben willst, so mußt du dies auch anlegen, d.h.
ausblenden C#-Quelltext
1:
int[] newArr = new int[Arr.Length]; // mit gleicher Größe wie das Array 'Arr'					

Um dann auch die Inhalte des Original-Arrays dort reinzukopieren, könnte man z.B. dann die Array.CopyTo()-Methode verwenden:
ausblenden C#-Quelltext
1:
Array.CopyTo(Arr, newArr, Arr.Length); // alle Elemente kopieren (daher Arr.Length als Anzahl)					

Explizit für Arrays gibt es aber auch die Array.Clone()-Methode, welches zumindestens für Wertetypen (innerhalb des Arrays) echte Kopien erzeugt, d.h.
ausblenden C#-Quelltext
1:
int[] newArr = (int[])Array.Clone(Arr);					

Der Cast (int[]) ist notwendig, weil Array.Clone beliebige Arrays (d.h. unterschiedlicher Typen) kopieren kann.
Bei dieser Art von Kopie spricht man auch von "flacher Kopie", da bei Referenztypen innerhalb des Arrays nur das Array selber kopiert werden würde (nicht aber die Elemente innerhalb des Arrays) - im Gegensatz zu einer "tiefen Kopie".

Ich hoffe, ich konnte dir damit diese Frage sinnvoll beantworten - und habe dich (als C#-Anfänger) nicht noch mehr verwirrt?

P.S. Unter 2.3.5 Einfache Datentypen im Buch "Visual C# 2010" gibt es ja auch eine kurze Erklärung bzgl. der Unterschiede von Werte- und Referenztypen (dies hast du wahrscheinlich bisher beim Durchlesen noch nicht als so wichtig erachtet bzw. den konkreten Sinn verstanden).
Mit den technischen Unterschieden (Stack vs. Heap) will ich dich jetzt auch noch gar nicht "quälen", sobald du jedoch weiter im Buch auf "Klassen" und "Objekte" stößt, solltest du dich an den Begriff "Referenztyp" erinnern.

Und schon mal als Ausblick:
Ein wichtige Ausnahme gibt es bei dem Datentyp "string": dieser ist zwar ein Referenztyp, wird jedoch wie ein Wertetyp behandelt. Bei Interesse kannst du dann mal den Artikel Besonderheiten der String-Klasse (immutabler Referenztyp mit Wertsemantik) lesen.

Für diesen Beitrag haben gedankt: jaenicke
ocram1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Sa 18.02.12 09:49 
Danke für die gute Erklärung.
Ich hab mir deinen Post ausgedruck werd ihn mitnehmen und wohl 10 mal durchlesen müssen damit ich das versteh.
Das Kapitel im Buch hab ich auch gefunden. Hab ich wirklich nicht beachtet beim lesen. Aber auch im nachhinein finde ich die Erklärung echt spärlich.
Denn wenn ich vom Verständis her schreibe
ausblenden C#-Quelltext
1:
newArr = Arr					

gehe ich davon aus das der ne Copy macht.
Das Kapitel hätten sie ausführlicher und mit Bsp machen sollen.

Danke für die tolle Erläuterung.
Find das Forum klasse. Ich finde mann braucht auch in der Startphase zwischendurch mal so Hilfen und Erklärungen.
Nich so wie in mycsharp.de.
Wos heist :"Wir wollen Anfänger zwar haben aber sie dürfen keine Fragen stellen..."

Grüsse und schönes WE noch.

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
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 18.02.12 13:51 
user profile iconocram1 hat folgendes geschrieben Zum zitierten Posting springen:
gehe ich davon aus das der ne Copy macht.
Um es noch einmal zu verdeutlichen: Es wird eine Kopie des Variableninhalts angelegt - nur ist das eben nur eine Referenz und nicht das Array-Objekt selbst ;) . Es gibt also kein grundsätzlich unterschiedliches Verhalten des Zuweisungsoperators bei Werte- und Referenztypen sondern es ist im zweiten Fall einfach immer eine Indirektion beteiligt.

_________________
>λ=
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 18.02.12 14:07 
user profile iconocram1 hat folgendes geschrieben Zum zitierten Posting springen:

Denn wenn ich vom Verständis her schreibe
ausblenden C#-Quelltext
1:
newArr = Arr					

gehe ich davon aus das der ne Copy macht.
Das Kapitel hätten sie ausführlicher und mit Bsp machen sollen.


In deinem Buch wird wahrscheinlich nie von kopieren gesprochen sondern üblicherweise von zuweisen. Es gibt glaube ich einfach Dinge die man sich nicht erlesen kann sondern erfahren muss. Es ist zu einfach die Wortwahl wie z.b. zuweisen anstatt kopieren für ein rein sprachliches Stilmittel zu halten ohne weitere Aussagekraft. Das was du durch dein Beispiel erfahren hast hätte man wahrscheinlich nie gut in einem Buch erklären können. Ein Buch das das versucht würde sich so langatmig anfühlen das du es nicht mehr lesen wollen würdest ;)

Zitat:
Welchen Sinn hat es ein Array zu kopieren wenn ich im Endeffekt immer auf die selben Adressen zugreife?


Nochmal. Es heißt zuweisen nicht kopieren ;) Wenn du zwei lokale Variablen betrachtest und dort eine Zuweisung machst wie in deinem Beispiel dann ja kann sich das unsinnig anfühlen (ist es auch). Du musst dir aber bewusst werden das das in deinem Buch nur Beispiele sind die mit dem größeren Kontext in einer Anwendung nur bedingt zusammenpassen und dich erstmal an das Verhalten der Programmiersprache heranführen sollen. Wenn du dir eine Anwendung vorstellst die aus mehrerern Klassen bestehen ist es ein übliches Problem das diese Klassen natürlich mit gemeinsames Daten arbeiten und dann willst du keine Kopie sondern man möchte das die Klassen auf das gleiche Object verweisen. Es ist der wesentlich wahrscheinlichere Fall das man einen Verweis aus das gleiche Object will und keine Kopie. Kopie ist auch etwas leicht daher gesagt. Überleg dir mal was den eine Kopie eines Arrays genau ist. Ein zweites Array das auf die selben Elemente verweist wie das erste? Oder sollen die Elemente im Array auch kopiert werden? Was ist wenn die Elemente im Array wiederum eine innere Struktur haben wie sollen die wiederum kopiert werden? Ein Kopie von etwas ist eigentlich nur klar definiert für einfache Datentypen (Wertetypen wie Integer etc. die das dann auch automatisch machen) darüber hinaus ist oft gar nicht klar was eine Kopie genau ist und der Vorgang des Kopierens muss explizit definiert und ausprogrammiert werden. Er lässt sich zumindest nicht durch einen bereits vorgegeben Operator einfach durchführen.