Laden...

Grundsatzfrage: new-keyword und Objekterzeugung

Erstellt von Fresh0razoR vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.977 Views
Thema geschlossen
F
Fresh0razoR Themenstarter:in
17 Beiträge seit 2011
vor 13 Jahren
Grundsatzfrage: new-keyword und Objekterzeugung

Hallo zusammen.

Aus Routine heraus verwende ich in C# für die Instanzerzeugung während der Laufzeit
in C# das new-Schlüsselwort. Also


Car mycar = new Car()

Nun frage ich mich jedoch, warum in C# das überhaupt notwendig ist. In C++ konnte manInstanzen ganz normal erzeugen wie sonst auch einen int oder float:

Car mycar();

Wenn man in C++ das new verwendet hat, dann in Verbindung mit einem Pointer. So konnte man per new und delete unzählige Instanzen zur Laufzeit erzeugen lassen und mit diesen dann Wild in allen Klassen damit arbeiten indem man einfach die Adresse des mit new erzeugten Objekts dem Pointer zugewiesen hat.Da Pointer in C# aber nicht mehr vorhanden sind, frage ich mich, wofür wir das in C# überhaupt noch brauchen!?

Danke & GrüßeFresh

Gelöschter Account
vor 13 Jahren

du kannst halt selbst entscheiden wann du das objekt erstellst.
bei der deklaration oder später(fallweise).

btw: pointer gibts in unsafe codeblöcken auch in c#

F
Fresh0razoR Themenstarter:in
17 Beiträge seit 2011
vor 13 Jahren

Ich meine jetzt natürlich ausschließlich im safe-modus.

Also was für einen Vorteil / Nachteil hätte denn das spätere erzeugen?

C
2.122 Beiträge seit 2010
vor 13 Jahren

In C# ist jede Variable eines Objekts praktisch immer noch ein Pointer.
Die Syntax aus C++ reicht bei weitem nicht aus, denn die bedeutet dass du pro deklarierter Variable immer genau ein Objekt hast. Dem ist aber nicht immer so, oft erzeugt man in einer Schleife mehrere Objekte pro Variable, oder mehrere Variablen zeigen auf das selbe Objekt. Die von die vorgestellte Deklaration in C++ macht im Hintergrund ja auch ein "new", nur brauchst du es da nicht ausdrücklich schreiben.

Das mit der Zuweisung von Objekten und dem wilden arbeiten kannst du in C# alles genauso tun. Nur spricht man da eben nicht mehr von Pointer, obwohl eigentlich das selbe dahinter steckt. Nur spricht man nicht mehr von Pointern Man sollte meiner Meinung auch nach wie vor wissen, was da unter der Haube passiert.

156 Beiträge seit 2010
vor 13 Jahren

Moin,


// C++
Car mycar = new Car(); // Variante 1
Car mycar();           // Variante 2

erste Variante erzeugt das Objekt auf dem Heap - letzte auf Stack ... der Stack wird beim verlassen der Methode aufgeräumt, somit auch das Objekt (Destruktor) ... soviel zu C++

Da Pointer in C# aber nicht mehr vorhanden sind,

Pointer gibt es (mehr oder weniger) immer noch in C# ... nennt sich jetzt Referenzen und der GC darf sie nach Bedarf im Speicher umherschieben ... über die Referenzen merken sich nur die Adresse im Speicher der vom GC veraltet wird ... es ist also ein Adresse wie beim Pointer ... Du kannst nur kein Schindluder wie bei C++ (oder andere Sprachen mit Pointern) treiben

frage ich mich, wofür wir das in C# überhaupt noch brauchen!?

aus dem gleichen Grund wie bei C++ ... damit die Objekte auf dem Heap landen und nicht im Stack ... der Stack ist meistens begrenzt (vgl. StackOverflowException) ... Arbeitsspeicher zwar auch (physikalisch), aber davon hast Du um einiges mehr

hand, mogel

btw. bitte ggf. um Korrekturen

771 Beiträge seit 2009
vor 13 Jahren

Hi mogel,

du meintest wohl


Car mycar;         // Variante 2

Deines wäre nämlich eine Deklaration eines Funktionszeigers. 😁

Ansonsten passen aber deine Aussagen.

S
248 Beiträge seit 2008
vor 13 Jahren

Hallo Fresh0razoR,

der Unterschied liegt darin, dass du in C++ Klassen wie Structs verwenden kannst:

Car mycar = Car();           // Variante 2

oder du kannst sie auf dem Heap erzeugen und so Polymorpie nutzen:

Car* mycar = new Car(); // Variante 1

Dies ist in C# nicht möglich. Structs werden immer auf dem Stack und Klassen immer auf dem Heap erzeugt (dabei verwenden beide Initialisierungen das new Schlüsselwort!).

spooky

F
Fresh0razoR Themenstarter:in
17 Beiträge seit 2011
vor 13 Jahren

Hallo zusammen,

ich muss gestehen, dass ich jetzt vollends verwirrt bin... 😃

Ich bin aber auch der Meinung, dass nicht alle hier aufgeführten Aussagen korrekt sind.

Zunächst möchten wir festhalten, dass es in C++ sowohl Pointer als auch Referenzen gibt. In C# jedoch nur noch Referenzen. Die Pointer in C# lassen wir wegfallen, da der Fokus in C# auf Typsicherheit liegen soll.

Weiterhin halten wir fest, dass der Stack wesentlich kleiner ist als der Heap. Der Stack ist schneller zu erreichen und somit schneller in der Verarbeitung.

Bis hierhin korrekt?

Wir haben nun die Klasse Car. In C++ kann ich nun in einer Methode eine Instanz erzeugen:


Car myCar;

Nach dieser Variante wird eine Instanz von Car auf dem Stack erzeugt. Sobald die Methode durch ist, wird die Instanz vom Stack gelöscht. Korrekt?

Will ich mit einer Instanz wild im Program hantieren ohne, dass es aufgrund der Funktionslokalität gelöscht wird, muss ich Pointer verwenden und die Adressen weitergeben. Die Instanz selbst wird von MIR verwaltet. Erst wenn ich explizit mit einem darauf zeigenden Pointer delete ausführe, wird das Teil ins Jenseits befördert. Korrekt?

Verwende ich in C++ dagegen eine Referenz, so ist das zunächst nur ein Alias für die gleiche Variable. Ich kenne keinen gescheiten Verwendungszweck für Referenzen in C++ außer bei der Übergabe an Funktionen (Call by Reference), um so direkt an der Variable zu basteln ohne eine Kopie übergeben zu müssen und diese per return wieder zurückzugeben, was umständlicher und langsamer als das direkte Ändern ist.

Sind alle d'accord bis hierhin?

Ab hier jetzt meine kritischen Fragen. Leider habe ich keinen Compiler hier um meine Aussagen zu testen, deshalb kritisch das folgende betrachten!
Kann man in C++ folgendes machen?


Car myCar;
Car yourCar;

...//myCar wird mit werten befüllt

//nun möchte ich das gefüllt mycar kopieren:

yourCar = myCar //Geht das???

Ich meine JA!! Wie schaut das in C# aus? Ich meine NEIN!
Wenn ich in C++ eine Instanz deklariere, so wird die auf dem Stack abgelegt. Mache ich mit new eine neue Instanz, so kommt die auf den Heap, korrekt?

Jetzt zu C#:
Wenn ich eine normale Instanz deklariere, was steht dann in meiner Variable? Die echte Instanz oder nur eine Speicheradresse? Mir ist die interne Verwaltung schon klar, jedoch geht es speziell darum, welche Zugriffsmöglichkeiten ich nun habe.

Genau hier liegt der Knackpunkt! Für mich ist es kein Unterschied, ob ich eine Instanz deklarativ erzeuge oder per new! Sicher gibt es einen, ich versteh ihn aber nicht...

Danke!!
Grüße
Fresh

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Fresh0razoR,

du schreibst im Titel, dass es eine Grundsatzfrage ist, aber es ist eher eine Grundlagenfrage, die in jedem guten C# Buch beantwortet wird. Ok, nicht unbedingt der Sinn, warum es so ist, aber immerhin doch wie es ist. Und so wie es ist, ist es gut.

Die meisten deiner Aussagen sind zwar korrekt, aber von der üblichen sehr technisches Sichtweise (Speicherverbrauch, Geschwindigkeit) von C++ geprägt. Wie es in C++ realisiert ist, ergibt sich aus dem historischen Erbe von C. Dabei kommt es eigentlich auf die Semantik an. Objektorientiert sauber ist es so, wie es in C# realisiert ist, nämlich dass es einen Unterschied zwischen Objekten und Variablen gibt. Variablen enthalten nur Verweise/Referenzen auf die Objekte, nicht die Objekte selbst. Mir liegt die objektorientierten Sichtweise, und ich habe schon zu C++-Zeiten jedem empfohlen, als Normalfall Variablen zu verwenden, die Objekte referenzieren, nicht die Objekte selbst in den Variablen zu speichern, also

Car *pmyCar = new Car ();

und eben nicht

Car myCar;

Leider muss man in C++ dadurch oft explizit mit Pointern arbeiten, weil Referenzen in C++ leider nur "write once" realisiert und damit oft unzureichend sind. In C# geht es endlich sauber, weil Variablen automatisch Verweise enthalten und trotzdem jederzeit änderbar sind. Ich kann dir nur dringend empfehlen, dich auf die objektorientierte Sichtweise, die in sehr gut C# umgesetzt wurde, einzulassen.

herbivore

Thema geschlossen