none
Referencen auf Objekte löschen RRS feed

  • Allgemeine Diskussion

  • Hallo,

    ich habe eine Klasse, welche eine recht große Struktur von Daten verwaltet.

    Dabei referenzieren diverse Objekte auf ein gemeinsames Objekt. Wenn ich nun dieses Objekt lösche sollen alle Referenzen in dieser Struktur auch aufgehoben werden.

    Dabei möchte ich nat. nicht über alle Typen der Struktur iterieren um die passenden Referenzen zu finden und auf zu heben.

    Gibt es eine einfachere Möglichkeit?

    Danke

    Dienstag, 3. Juni 2014 11:51

Alle Antworten

  • Hi,

    poste bitte ein reduziertes Beispiel bzw. den Code des reduzierten Beispiels und erläutere anhand des Beispielcodes, was genau wo passieren soll.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Dienstag, 3. Juni 2014 12:12
    Moderator
  • Hi,
    eine einfache Lösung ist die Nutzung von Eigenschaften. Die Referenzen auf ein Objekt werden alle "kanalisiert" über eine Eigenschaft, d.h. alle Zugriffe nutzen nur die Eigenschaft. In der Eigenschaft brauchst Du nur an einer Stelle dann den Verweis vernichten und kannst auch noch alle anderen Zugriffe überwachen, um z.B. fehlerhafte Abläufe zu erkennen oder ggf. eine neue Instanz bereitzustellen.

    --
    Peter

    Dienstag, 3. Juni 2014 17:51
  • Hi,

    poste bitte ein reduziertes Beispiel 

    namespace MSDN
    {
        class TypeA
        {
            public int Property1 { get; set; }
            public int Property2 { get; set; }
        }
    
    
        class ClassList : List<TypeA>
        {
        }
    
        class ClassStrukture
        {
            public TypeA Class1 { get; set; }
            public ClassList ClassListOfTypeA { get; set; }
        }
    }
    

    Die ClassStrukture ist natürlich wesentlich komplizierter und unübersichtlicher und es ist kaum möglich da alles zu iterieren. Alleine um die Funktion zu schreiben und aktuell zu halten wäre der Aufwand sehr hoch und fehlerträchtig. Die Zuweisung der Klassen ist auch eher caotisch. 

    Wenn ich also eine Klasse vom TypeA habe, dann will ich alle Referencen der Classtrukture auf sie, automatisch löschen können. Die Klasse selbst kann dann auch verschwinden, wenn der CarbageCollector seine Arbeit macht.

    Oder kann der Garbage Collector den Job übernehmen?

    Mittwoch, 4. Juni 2014 09:30
  • Hi,
    eine einfache Lösung ist die Nutzung von Eigenschaften. 

    Ich kann die Klasse nicht zentral zuweisen, das wird letztlich manuell gemacht und ist von vielen Faktoren abhängig.

    Mittwoch, 4. Juni 2014 09:36
  • Hi,

    eine Klasse kannst Du nicht löschen, wenn, dann nur die Instanz(en) dieser Klasse.

    Aber ehrlich gesagt habe ich immer noch nicht verstanden, wo genau das Problem liegt.

    Was genau soll denn in der Instanz von ClassStrukture gelöscht werden und wann soll das passieren?

    Falls dir vorschwebt, zum Zeitpunkt X bspw. sowohl Class1 als auch alle Elemente innerhalb ClassListOfTypeA sowie ggfs. ClassListOfTypeA automatisch terminieren zu lassen, wirst Du das manuell machen müssen.

    Ich sehe aber da derzeit noch keinen Sinn dahinter, daher wäre es (zumindest für mich) notwendig, dass Du mal an einem praktischen und nachvollziehbaren Beispiel genau beschreibst, was Du wann wo erzeugst, was wann passieren soll (bitte dabei dann immer Bezug auf die genauen Instanzen, Eigenschaften, ... nehmen)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Mittwoch, 4. Juni 2014 09:46
    Moderator
  • Hallo,
    wenn ich dich richtig verstehe, hast du folgendes vor:

    Du willst eine Instanz von TypeA löschen. Eine Instanz von ClassStructure verweißt auf die TypeA-Instanz. Sobald TypeA gelöscht wird, soll auch ClassStructure gelöscht werden.

    Das geht so aber nicht. Eine Klasse wird vom GC solange beibehalten, wie noch eine Referenz auf sie vorliegt. Dieser bleibt durch die Eigenschaft ClassStructure.Class1 erhalten.

    Nach dem was ich momentan über dein Projekt weiß, macht dein Vorhaben für mich auch keinen Sinn.
    Um alles auf einmal zu vernichten bräuchtest du IMHO eine Klasse die sämtliche Instanzen verwaltet. Ähnlich zum GC.


    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Mittwoch, 4. Juni 2014 10:07
    Moderator
  • Hallo umocomp1,

    ich denke hier vielleicht schlichter als meine Vorgänger ... aber:

    TypeA hat keine Referenzen auf ClassList oder Classstruktur: Damit kann von dort aus das übergeordnete Objekt nicht freigegeben werden.

    ClassList steckt in ClassStruktur und hat genauso wie TypeA keine Referenz auf das übergeordnete Objekt.

    Wenn ClassStruktur so benutzt worden ist:

    ClassStruktur cs = new ClassStruktur(); cs.Class1 = new TypeA(); cs.ClassListOfTypeA.add( new TypeA() );
    cs.ClassListOfTypeA.add( new TypeA() );

    dann reicht es IMHO aus, allein cs auf null zusetzen

    cs = null;

    und den Rest dem Garbage Collector zu überlassen.

    Schwieriger ist es, wenn TypeA unmanged Objekte enthält die manuell freigegeben werden müssen.

    Frohes Schaffen

    Niels

    Mittwoch, 4. Juni 2014 12:28
  • Hallo umocomp1,

    am einfachsten ist es glaube ich sich eine Referenzen als Pfeil von einer Instanz auf eine andere vorzustellen. Wenn du dann die Referenz auf null setzt nimmst du den Pfeil weg. Wenn kein Pfeil mehr die Instanz zeigt, kann der GC sie entfernen.

    z.B. (alle Zeigen auf A)

    B->A

    C->A

    D->A

    Eine einfache Sache die du hier machen kannst ist, die Instanz eines anderen Objektes da Zwischen schalten, welches die Referenz auf A hat. Wenn du dann da die Referenz auf A entfernst hat keiner mehr die Referenz auf A.

    Das sah ungefähr so aus.

    B->E->A

    C->E->A

    D->E->A

    Und nach entfernen der Referenz:

    B->E

    C->E

    D->E

    Dann kannst du Peters Vorschlag umsetzen in die Klasse A (A* im weiteren) eine Eigenschaft hat welche die Referenz auf die Instanz von A hat. Das entspricht (nicht ist) dem Singel-Ton Pattern (Was aber auch bei manchen als Anti-Pattern gilt).

    Das sah ungefähr so aus.

    B->A*->A

    C->A*->A

    D->A*->A

    Und nach entfernen der Referenz (Wobei A* keine Instanz ist):

    B->A*

    C->A*

    D->A*

    Theoretisch kann man auch was ganz ungewöhnliches machen. B,C und D von einer gemeinsamen Basis Klasse erben Lassen und bei der Benutzung von A, an A übergeben. Dann könnte A die Referenzen auf sich entfernen. Das ist aber wirklich nicht schön.

    Wenn keine Referenz mehr auf B,C und D existiert, wird übrigens auch A vom GC weg geräumt. (Das ist dass was Niels meint.)

    Was dir vielleicht weiter hilft ist eine Week Referenz, das kommt aber darauf an was du genau machst.

    @Niles: Wenn A unmanaged Objekte enthält, sollte A auch korrekt Dispose (mit dem Finilizer) implementieren. Dann räumt der GC es auch weg. Na ja solange da nicht auf dem Speicher gepinnt wird, wie z.B. im Timer.

    Mit freundlichen Grüßen

    Björn

    Mittwoch, 4. Juni 2014 16:00
  • Hi,
    ein Anwender kann nicht manuell irgend etwas zuweisen. Das können nur Entwickler. Und, wenn die entsprechenden Zugriffsmodifizierer gesetzt sind, meldet sich der Compiler. Dann ist ggf. für alte "Sünden" etwas Handarbeit erforderlich.

    Du solltest zur Lösung des Problems nochmals genauer beschreiben, welche Entwicklungsrichtlinien zu diesem Zustand geführt haben.

    --
    Peter

    Mittwoch, 4. Juni 2014 19:20