Entwickler-Ecke

Sonstiges (.NET) - gleiches objekt mehrmals erstellen


uwe1234 - Mi 31.08.11 17:56
Titel: gleiches objekt mehrmals erstellen
Hallo zusammen,

ich habe eine einfache Frage.

C#-Quelltext
1:
2:
3:
4:
5:
6:
private void button19_Click(object sender, EventArgs e)
    {
      Ware produkt1 = new Ware();
      produkt1.Produkt = "TEST";
      labelZA.Text = produkt1.Produkt;
    }

Wenn ich den Button drücke wird das Objekt produkt1 erstellt usw. Was passiert mit dem Objekt wenn ich den Button
nochmals drücke. Laut meinem debugger wird das Objekt erneut erstellt oder sehe ich das falsch? Ist das ein Problem,
wenn auf diese Art das Objekt erneut erstellt wird?

Danke und Gruß
Uwe


Kha - Mi 31.08.11 18:01

new erstellt nunmal ein Objekt der angegebenen Klasse, also ja ;) . Auf das Objekt des letzten Klicks hast du keinen Zugriff, da du ja keine Referenz mehr hältst.
Was für Probleme stellst du dir denn vor? Zu einem Performance-Problem wird das jedenfalls erst, wenn du die Methode einmal pro Mikrosekunde ausführst.

Edit: Um es sprachlich noch einmal festzunageln: Es wird nicht das gleiche Objekt mehrmals erstellt, sondern Objekte (= Instanzen) der gleichen Klasse. Ebenso ist es nicht möglich, ein Objekt "erneut zu erstellen".


uwe1234 - Mi 31.08.11 18:37

Hallo,

ich habe mir die Punkte Destruktor, Garbage Collector und Dispose angeschaut. Dabei ist mir die Frage aufgekommen,
was mit den Objekten (Instanzen) bei meinem Beispiel passiert, wenn ich den Button mehrmals drücke. Was passiert mit den Instanzen bei denen die Referenz nicht mehr gehalten wird? Belegen diese z.B. Speicher etc.?

Ich möchte C# lernen, und vielleicht auch mal verstehen, und nicht nur irgendwelche Programmcodes die ich irgendwo her habe zusammenführen. Daher meine Frage.


Danke und Gruß


Kha - Mi 31.08.11 19:29

user profile iconuwe1234 hat folgendes geschrieben Zum zitierten Posting springen:
Was passiert mit den Instanzen bei denen die Referenz nicht mehr gehalten wird?
Wenn wirklich keinerlei Referenz mehr existiert, ist das Objekt "eligible for garbage collection", wann auch immer diese dann passieren mag (nicht-deterministische Freigabe).


stes - Mi 31.08.11 22:26

Hallo,

nochmal zu deinen Fragen:

user profile iconuwe1234 hat folgendes geschrieben Zum zitierten Posting springen:
Dabei ist mir die Frage aufgekommen,
was mit den Objekten (Instanzen) bei meinem Beispiel passiert, wenn ich den Button mehrmals drücke. Was passiert mit den Instanzen bei denen die Referenz nicht mehr gehalten wird? Belegen diese z.B. Speicher etc.?
Danke und Gruß


so wie du es machst belegt das ganze keinen zusätzlichen Speicher, da du dein Objekt ja quasi ständig mit einer neuen Instanz der Klasse überschreibst. Das "alte" Objekt muss dafür gewissermaßen den Platz räumen.

Anders ist es, wenn du die Objekte "aufbewahrst", z.B. in einer ArrayList speicherst. Hierzu zwei Beispiele:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
        static void Main(string[] args)
        {
            while(true)
            {
                Object o = new Object();
            }
        }


Wenn du eine Konsolenanwendung mit dieser Hauptprozedur erstellst und dir den Prozess im Taskmanager anschaust, ist der Speicherbedarf der Anwendung (näherungsweise) konstant. Anders wenn du folgenden Code ausführst:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
        static void Main(string[] args)
        {
            System.Collections.ArrayList list = new System.Collections.ArrayList();
            while(true)
            {
                list.Add(new Object());
            }
        }


Wenn du dieses Programm ausführst und dir den Taskmanager anschaust, kannst du sehen wie der Speicherbedarf regelrecht in die Höhe schnellt (irgendwo ja logisch). Das ganze endet dann in einer OutOfMemoryException (bei mir bei ~1GB Speicherbedarf).

Weitere Infos zum Thema auch bei VC# openbook, Kapitel "Zerstören von Objekten"/GC [http://openbook.galileocomputing.de/visual_csharp_2010/visual_csharp_2010_04_008.htm#mj5c9073a7a50b2e0c07435459352f3a2b]

Gruß
stes


Kha - Mi 31.08.11 22:49

user profile iconstes hat folgendes geschrieben Zum zitierten Posting springen:
so wie du es machst belegt das ganze keinen zusätzlichen Speicher, da du dein Objekt ja quasi ständig mit einer neuen Instanz der Klasse überschreibst. Das "alte" Objekt muss dafür gewissermaßen den Platz räumen.
Das stimmt einfach nicht. Es können beide Instanzen gleichzeitig im Speicher sein, wenn man zweimal nacheinander auf den Button drückt, ist das sogar relativ wahrscheinlich. Natürlich wird aber spätestens vor einer OOM-Exception eine Full Collection durchgeführt, den Speicher ganz füllen kann man sich damit nicht.


stes - Mi 31.08.11 23:27

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Das stimmt einfach nicht. Es können beide Instanzen gleichzeitig im Speicher sein, wenn man zweimal nacheinander auf den Button drückt, ist das sogar relativ wahrscheinlich.


Ok ich sehe es ein :D Gerade einen Artikel gefunden: Artikel über den Managed Heap in C# [http://www.codeguru.com/columns/dotnet/article.php/c6593].
Demnach wäre es allerdings so (etwa bei meinem ersten Beispiel), dass die Objekte in der ersten Generation des managed heap hängen bleiben und relativ schnell (da wenig Speicher für die erste Generation reserviert ist) wieder vom GC aufgelesen werden, was darin resultiert, dass im Taskmanager keine Veränderungen am Speicherbedarf erkennbar sind, soweit sachlich korrekt? ;)

Gruß
stes


Kha - Mi 31.08.11 23:33

Dass sie Generation 0 nicht verlassen, kannst du nicht garantieren, aber ja, es ist sehr wahrscheinlich :) . Solche kurzlebigen Objekte haben GCs am liebsten.


stes - Mi 31.08.11 23:44

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Dass sie Generation 0 nicht verlassen, kannst du nicht garantieren, aber ja, es ist sehr wahrscheinlich


Also ich könnte mir keinen "wahrscheinlicheren" Fall denken, als jenen beschriebenen bei dem der Variablen bei jeden Schleifendurchlauf direkt eine neue Instanz zuteil wird ^^


uwe1234 - Do 01.09.11 08:46

Das bedeutet für mich um es kurz zu fassen:
Instanzen (die die Referenz verloren haben) bleiben für eine unbestimmte Zeit im Speicher als "leichen" erhalten, bis der GC sie aufräumt, korrekt?
Durch welche Bedingungen verliert eine Instanz die Referenz, außer durch mein Beispiel?


dark-destination1988 - Do 01.09.11 10:05

lokales objekt in methode--> nach verlassen der methode


Ralf Jansen - Do 01.09.11 10:37

Zitat:
Durch welche Bedingungen verliert eine Instanz die Referenz, außer durch mein Beispiel?

Näherungsweise immer dann wenn der Scope [http://msdn.microsoft.com/en-us/library/aa691132.aspx] in dem die Referenz definiert wurde zu Ende ist.


Th69 - Do 01.09.11 12:54

Und bei Containern durch z.B. list.Remove(object), d.h. wenn ein anderes Objekt diese Referenz auf das Objekt verwirft.

Eine Referenz auf ein Objekt geht auch bei Zuweisung eines anderen Objekts (bzw. null) verloren, z.B.

C#-Quelltext
1:
2:
3:
4:
5:
6:
other_object.obj_ref = new Object();

Object o = new Object();
other_object.obj_ref = o; // <- Referenz auf obiges anonymes Objekt wird verworfen

other_object.obj_ref = null// <- Referenz auf Objekt o wird verworfen


Yogu - Do 01.09.11 14:28

user profile iconuwe1234 hat folgendes geschrieben Zum zitierten Posting springen:
Durch welche Bedingungen verliert eine Instanz die Referenz, außer durch mein Beispiel?

Eigentlich immer dann, wenn es garantiert ist, dass niemand mehr danach drauf zugreifen wird. Das kann auch schon vor dem Verlassen des Scopes passieren, und zwar, wenn innerhalb der Methode einfach nichts mehr mit dem Objekt gemacht wird:


C#-Quelltext
1:
2:
3:
4:
5:
6:
void test() {
  MyClass obj = new MyClass();
  obj.DoSomething();
  // Ab hier wird obj nicht mehr benötigt, kann also entfernt werden
  Console.WriteLine("Something done.");
}

Im Prinzip brauchst du dich darum überhaupt nichts zu kümmern, das macht alles das Framework.


uwe1234 - Do 01.09.11 21:48

Hallo zusammen,

danke für die Infos. Bin jetzt diesbezüglich etwas schlauer :)

Gruß


pdelvo - Sa 03.09.11 16:16

Oder wenn es nurnoch Referenzen über eine WeakReference gibt