Instanzen-Tracker: So richtig?



  • Hallo,

    ich hätte mal eine grundsätzliche Frage zu Klassen bzw. wie diese wieder "weggeräumt" werden. Und zwar, ist folgende Klasse "sicher"?

    public class Foo
    {
        private static Dictionary<Foo, int> instanceMap = new Dictionary<Foo, int>();
    
        public Foo(int val)
        {
            instanceMap.Add(this, val);
        }
    
        ~Foo()
        {
            instanceMap.Remove(this);
        }
    
        public static int GetVal(Foo foo)
        {
            return instanceMap[foo];
        }
    }
    

    Also kann man sich sicher sein dass ein Objekt auch immer nur einmal in der map sein wird? Also dass durch das Remove im Destruktor die map wieder rechtzeitig freigeräumt wird?

    Oder gibt es hier irgendwelche gemeinen Fallstricke?



  • happystudent schrieb:

    ich hätte mal eine grundsätzliche Frage zu Klassen bzw. wie diese wieder "weggeräumt" werden. Und zwar, ist folgende Klasse "sicher"?
    ...
    Oder gibt es hier irgendwelche gemeinen Fallstricke?

    Als Fallstrick sehe ich hier das nicht-deterministische Verhalten von C# (Destruktur) und ggf. Threading an.



  • Was den "Destruktor" (Finalizer) angeht wird sich das völlig deterministisch verhalten. Der wird einfach nie aufgerufen werden, alle Objekte werden ewig im Dictionary bleiben. Weil die Objekte nicht collected werden können solange das Dictionary noch Referenzen drauf hat.

    Wenn dann müsste man sowas wie ConditionalWeakTable nehmen.
    https://msdn.microsoft.com/en-us/library/dd287757.aspx?f=255&MSPPError=-2147217396

    Womit dann auch das "nicht threadsafe" Problem gelöst wäre.
    Dann gibt es allerdings das Problem dass die Objekte nicht deterministisch eingesammelt werden.



  • asc schrieb:

    Als Fallstrick sehe ich hier das nicht-deterministische Verhalten von C# (Destruktur) und ggf. Threading an.

    hustbaer schrieb:

    Was den "Destruktor" (Finalizer) angeht wird sich das völlig deterministisch verhalten Der wird einfach nie aufgerufen werden, alle Objekte werden ewig im Dictionary bleiben. Weil die Objekte nicht collected werden können solange das Dictionary noch Referenzen drauf hat.

    Mist, das hatte ich befürchtet 😞

    hustbaer schrieb:

    Wenn dann müsste man sowas wie ConditionalWeakTable nehmen.
    https://msdn.microsoft.com/en-us/library/dd287757.aspx?f=255&MSPPError=-2147217396

    Womit dann auch das "nicht threadsafe" Problem gelöst wäre.

    Ok, das klingt schonmal gut... allerdings scheint das erst ab 4.0 zu sein, gibts da vielleicht ein äquivalent für 3.5?

    hustbaer schrieb:

    Dann gibt es allerdings das Problem dass die Objekte nicht deterministisch eingesammelt werden.

    Hm, bin mir nicht sicher was damit gemeint ist... So wie ich die Doku verstehe wird irgendwann (nicht-deterministisch) das Objekt aus dem Dictionary entfernt - Also wär das einzige Problem dass eventuell mehr Einträge im Dictionary sind als aktuell noch existieren, richtig?

    Zu Kollisionen kann es dann aber trotzdem nicht kommen, oder?



  • Zu Kollisionen kann es sowieso nie kommen.



  • Ok, das ist schonmal gut...

    Kann man so einen Mechanismus dann auch irgendwie ohne ConditionalWeakTable (also nur mit 3.5 Mitteln) erreichen?

    Oder bleibt einem nichts anderes übrig als eine "Remove" Metode zu implementieren und hoffen dass der Benutzer diese auch immer brav aufruft? Das könnte dann problematisch werden...



  • Sollte sich schon machen lassen.
    Bis auf ein paar spezielle Kleinigkeiten die ConditionalWeakTable macht die du vermutlich nicht brauchst.

    Aber warum sagst du uns nicht erstmal was du eigentlich erreichen willst. Und idealerweise das X und nicht das Y.

    ps: Object.GetHashCode und WeakReference kennst du, oder?



  • hustbaer schrieb:

    ps: Object.GetHashCode und WeakReference kennst du, oder?

    Nein, WeakReference kannte ich noch nicht. Schonmal sehr gut zu wissen dass es sowas gibt. 👍

    hustbaer schrieb:

    Sollte sich schon machen lassen.
    Bis auf ein paar spezielle Kleinigkeiten die ConditionalWeakTable macht die du vermutlich nicht brauchst.

    Aber warum sagst du uns nicht erstmal was du eigentlich erreichen willst. Und idealerweise das X und nicht das Y.

    Also das Problem (sozusagen das 😵 ist, dass ich mit einer ziemlich großen, statischen Klasse arbeiten muss. Diese Klasse ist nicht von mir geschrieben und soll (bzw. muss) auch statisch bleiben, da die in der Form in vielen Projekten verwendet wird.

    Es wäre aber wesentlich praktischer, wenn man die Klasse instanziieren könnte, da die Klasse auch einen Zustand hat und man manchmal mehrere Zustände auf einmal haben will. Momentan ist das ziemlich umständlich.

    Meine Idee wäre jetzt, mir eine Wrapper-Klasse zu bauen, welche intern den Zustand der statischen Klasse verwaltet (auf die Idee dazu bin ich über unsere letzte Diskussion im WinAPI Forum gekommen, da das ein relativ ähnlich Problem war, wenn auch in C++).

    Ziel ist dass ich die statische Klasse wie eine ganz normale Klasse verwenden und instanziieren kann, im Hintergrund aber immernoch die ursprüngliche Klasse verwendet wird.


Anmelden zum Antworten