Laden...

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

Erstellt von CrocodileDundee vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.602 Views
C
CrocodileDundee Themenstarter:in
51 Beiträge seit 2018
vor 4 Jahren
Lebensdauer von Objekten; Werden Subklassen nicht mit zerstört?

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!

T
2.219 Beiträge seit 2008
vor 4 Jahren

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.

849 Beiträge seit 2006
vor 4 Jahren

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.

C
CrocodileDundee Themenstarter:in
51 Beiträge seit 2018
vor 4 Jahren

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!

1.029 Beiträge seit 2010
vor 4 Jahren

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

4.931 Beiträge seit 2008
vor 4 Jahren

Das "auf null setzen" ist überflüssig, wenn direkt darauf wieder ein neues Objekt erzeugt wird (nicht, daß du dir das als Pattern aneignest 😉

C
CrocodileDundee Themenstarter:in
51 Beiträge seit 2018
vor 4 Jahren

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?

1.029 Beiträge seit 2010
vor 4 Jahren

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

4.931 Beiträge seit 2008
vor 4 Jahren

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.

T
2.219 Beiträge seit 2008
vor 4 Jahren

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.