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

  • »
  • Community
  • |
  • Diskussionsforum
Lebensdauer von Objekten; Werden Subklassen nicht mit zerstört?
CrocodileDundee
myCSharp.de - Member



Dabei seit:
Beiträge: 54

Themenstarter:

Lebensdauer von Objekten; Werden Subklassen nicht mit zerstört?

beantworten | zitieren | melden

Hallo zusammen,
habe eine Klasse, in der ich wiederum eine Klasse instanziere:


public class Class1
{
    public Subclass SubKlasse = new Subclass();
    ....
}

In meiner Main-Routine instanziere ich dann Class1:


Klasse1 = new Class1();

so daß ich dann auch auf die SubKlasse zugreifen kann.


Klasse1.SubKlasse.Prop = 0;

Soweit alles gut.

Wenn ich nun aber die Klasse1 zerstöre und später wieder
instanziere


Klasse1 = null;
...
Klasse1 = new Class1();

bekomme ich eine Exception, weil anscheinend die Instanz der Subklasse noch immer im Speicher ist.
Kann das sein? Wird die Subklasse nicht mit zerstört?

Vielen Dank!
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1892
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Auf den ersten Blick kann es nicht sein, dass die SubClass Instanz noch im Speicher hängt.
Wenn dein Objekt auf Null gesetzt wird, geht die alte Instanz samt Daten verloren.
Von deinem Code her, wäre deine SubClass mit einem neuen Objekt auch direkt wieder instanziert.

Du solltest auch mit Properties arbeiten.
Direkte Zugriffe auf die Felder einer Klasse verstoßen gegen die Kapselung der Daten in der OOP!
Bitte mal die Exception posten, diese kann hier nicht korrekt sein oder dein Code passt nicht/ist nicht korrekt!

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
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

Hi,

kommt immer darauf an was Du in deine Class1 oder Subclass so treibst. Wenn das wirklich wie dargestellt nur simple POCOS sind, sollte das tatsächlich so funktionieren.

Die erste Instanz würde aber trotzdem noch eine weile im Speicher verbleiben, bis der Garbage Collector sich bemüht das Ding mal endgültig aus dem Speicher zu werfen.

Hast Du nun irgendwelche Resourcen gebunden, die nicht vernünftig abgeräumt wurden, kann es durchaus zu Exceptions kommen.

Ausserdem kann man noch sehr böse Sachen in Konstruktor oder Property Machen die solche Sachen hervorrufen. Aber wie T-Virus schon schreibt ohne Exception oder Code kann man hier nur raten.
private Nachricht | Beiträge des Benutzers
CrocodileDundee
myCSharp.de - Member



Dabei seit:
Beiträge: 54

Themenstarter:

beantworten | zitieren | melden

OK, ich denke ich hab das Problem anscheinend nicht ausführlich genug geschildert.

Im Grund genommen geht es darum, daß ich eine private Property ändern möchte, die nur über den Konstruktor erreichbar ist.
Konkret geht es darum, daß ich ein Objekt ("Klasse1") instanziere, wobei ich den Namen einer COM-Schnittstelle im Konstruktor angeben muss.


Class1 Klasse1 = new Class1(COM1);


War es die falsche Schnittstelle (d.h. keine Kommunikation), war der Plan, das Objekt auf "null" zu setzen, und mit dem Namen einer anderen Schnittstelle neu zu instanzieren.


Klasse1 = null;
Klasse1 = new Class1(COM2);

Beim neuen Instanzieren von Class1 tritt nun die Exception auf.
Der Fehler tritt da auf, wo der Konstruktor der Subklasse durchlaufen wird.


public class Class1(string COMPortName)
{
    public Subclass SubKlasse = new Subclass();
    ...
}


public class Subclass
{
    DataTable dt = new DataTable();

    public Subclass() 
    }
        dt.Columns.Add("Sp1");      // Hier wird die Exception geworfen
        dt.Columns.Add("Sp2");
        dt.Columns.Add("Sp3");
    }
}



Der Compiler meldet zur Laufzeit:
"Additional information: Eine Spalte names 'Sp1' gehört bereits zu dieser DataTable."

Ich kann mir das nur so erklären, daß das Objekt noch im Speicher hängt und noch nicht vom Garbage Collector bereinigt wurde.
Einen "GC-Collect()" hab ich auch schon eingefügt, bringt aber auch nix.

Danke!
private Nachricht | Beiträge des Benutzers
Taipi88
myCSharp.de - Member

Avatar #avatar-3220.jpg


Dabei seit:
Beiträge: 1044
Herkunft: Mainz

beantworten | zitieren | melden

Hi,

du hast Recht und auch wieder nicht.

Du arbeitest beim zweiten Aufruf offenkundig mit der selben Instanz der Datentabelle - das ist ganz offensichtlich aber kein GarbageCollection-Fehler - sondern ein Fehler auf deiner Seite.

Dein Code hier könnte nicht kompilieren, ich habe ihn somit folgendermaßen gestaltet:


using System.Data;

namespace ConsoleApp8
{
    class Program
    {
        public static void Main(string[] args)
        {
            var Klasse1 = new Class1("COM2");
            Klasse1 = null;
            Klasse1 = new Class1("COM1");
        }
    }

    public class Class1
    {
        public Subclass SubKlasse = new Subclass();

        public Class1(string COMPortName)
        {
            
        }
    }

    public class Subclass
    {
        DataTable dt = new DataTable();

        public Subclass()
        {
            dt.Columns.Add("Sp1");      // Hier wird die Exception geworfen
            dt.Columns.Add("Sp2");
            dt.Columns.Add("Sp3");
        }
    }
}

Führt man das aus - funktioniert es problemlos. Um dir allerdings einen Hinweis zu geben:
Deklariert man nun z.B. die DataTable als static, also:


static DataTable dt = new DataTable();
Dann wird einem exakt die von dir genannte Exception um die Ohren gehauen. Mein Tipp: Mach dich auf die Suche wo du etwas ähnliches machst - der Code der dem Forum zur Verfügung steht ist jedenfalls nicht zu dieser Exception in der Lage.

LG
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4134

beantworten | zitieren | melden

Das "auf null setzen" ist überflüssig, wenn direkt darauf wieder ein neues Objekt erzeugt wird (nicht, daß du dir das als Pattern aneignest ;-)
private Nachricht | Beiträge des Benutzers
CrocodileDundee
myCSharp.de - Member



Dabei seit:
Beiträge: 54

Themenstarter:

beantworten | zitieren | melden

Zitat von Taipi88
Hi,
Deklariert man nun z.B. die DataTable als static, also:


static DataTable dt = new DataTable();
Dann wird einem exakt die von dir genannte Exception um die Ohren gehauen.
LG

Du hattest Recht, die DataTable war als static deklariert.

Also sind dann anscheinend statische Properties einer Klasse auch dann noch im Speicher,
selbst wenn kein Objekt der Klasse mehr existiert.

Kann es ein, daß diese Properties dann über die gesamte Lebensdauer des Programms im Speicher gehalten werden?
private Nachricht | Beiträge des Benutzers
Taipi88
myCSharp.de - Member

Avatar #avatar-3220.jpg


Dabei seit:
Beiträge: 1044
Herkunft: Mainz

beantworten | zitieren | melden

Hi,

siehe auch: https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/keywords/static

Solche statischen Objekte sind per AppDomain (also i.d.R. je Programm) einmalig vorhanden - und unter normalen Umständen vermeidet man die Verwendung dieses Modifikators. (Gibt einige Ausnahmen - eine DataTable ist aber definitiv und unter keinen Umständen ein Kandidat für eine solche Ausnahme)

--> Solange du die MSDN dazu nicht gelesen und verstanden hast solltest du static dementsprechend überhaupt nicht verwenden.

LG
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4134

beantworten | zitieren | melden

Ja, das ist der Sinn von statischen Objekten (es gibt ja auch statische Klassen, von denen keine Instanzen erzeugt werden können - und dann würden deren statischen Member sonst niemals erzeugt werden).
Die statischen Objekte existieren also komplett unabhängig von der Existenz anderer Objekte, sie werden sogar bei direkter Zuweisung schon vor allen anderen Objekten bei Programmstart erzeugt.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1892
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Im Regelfall solltest du solche static Objekte auch vermeiden.
Nur wenn es eine Notwendigkeit sollte man static Objekte verwenden.
Das Problem dabei ist, dass diese Objekte ohne zutun die gesamte Laufzeit lang den benötigten Speicherplatz verbrauchen.
Und je nach Menge/Größe der Objekte kann dies mit der Zeit einiges an RAM sein.
Zusätzlich haben solche Objekte, wie in deinem Fall, dann Seiteneffekte die man ohne genaue Prüfung dann erst einmal nachverfolgen und lösen muss.

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers