Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

De_Struktor

unregistriert

1

18.05.2013, 09:39

IDisposable

Hallo,

Ich hatte in einigen Projekten, die ich mir mal aus reinem Interesse angeschaut hatte, gesehen, das oft das Interface "IDisposable" in Einsatz kommt. Und da ich mir auch, speicherfreundlich programmieren will, ist es meine Frage an euch, wie ich dieses Interface richtig und konsequent einsetze? Mein Buch, das ich benutze, klärt nicht so gut darüber auf und im Internet finde ich leider nur unzureichende Praxisanwendungen.

Das Beispiel auf MSDN muss ich ehrlich zu geben, kann ich nicht so ganz nachvollziehen.

Würde mich über ne kurze Erklärung sehr freuen.

Mfg

DeStruktor

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

2

18.05.2013, 13:47

Was kannst du denn an dem MSDN Beispiel nicht nachvollziehen?

Atze12321

Frischling

Beiträge: 15

Wohnort: Jena

Beruf: Schüler...

  • Private Nachricht senden

3

18.05.2013, 13:59

IDisposable hat im Prinzip die Funktion, eine Möglichkeit zu schaffen, eine Instanz zu einem festen Zeitpunkt zu "zerstören" (mir ist grad kein besseres Verb eingefallen...)

Wenn du z.B eine offene Datenbankverbindung hast oder eine Klasse, z.B. eine Textur o.ä., die viel Arbeitsspeicher verbraucht (und nicht verwaltete Ressourcen belegt) hast, und du die Verbindung im Destruktor schließt oder die Textur im Destruktor freigibst, hast du das Problem, das die Verbindung/Textur erst geschlossen/freigegeben wird, wenn der Garbage Collector sich dazu entschließt, die Instanz zu beseitigen, und dieser Zeitpunkt ist unbestimmt.

Genau deswegen gibt es IDisposable, denn damit wird einem eine einheitliche (weil interface ;)) Möglichkeit geboten, Ressourcen zu einem festgelegten Zeitpunkt freizugeben. Mit IDisposable kann man dann auch z.B. Gebrauch von using-Blöcken machen.
8)

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

4

18.05.2013, 14:04

Also, .NET hat ja einen Garbage Collector. D.h. ab und an während dein Programm läuft guckt der nach welche Objekte noch in Benutzung sein könnten, da es noch Referenzen auf sie gibt, und gibt den Rest frei.

IDisposable kommt nun bei ein paar Fällen ins Spiel:

1) Dieses relativ zufällige freigeben reicht nicht. Das ist beispielsweise beim Umgang mit Dateien oder Netzwerkverbindungen der Fall. Die zuständigen Klassen stellen zwar typischerweise eine Close-Methode auf um die Resource deterministisch freizugeben, implementieren aber ebenso typischerweise auch IDisposable.

2) Es gibt Interop mit unmanaged Ressourcen. Diese kann der Garbage Collector nicht freigeben.

Evtl. gibt es noch mehr Fälle, die sind aber alle relativ ähnlich. Es geht immer um Ressourcen, die der Garbage Collector nicht freigeben kann oder wo der Zeitpunkt zu undefiniert wäre.

Fall 2 lässt sich auch theoretisch durch Finalizer behandeln. Finalizer haben aber einen Nachteil: Der GC kann das Objekt nicht direkt freigeben und gibt es erst in eine Finalizerqueue, die nach und nach auf einer CPU abgearbeitet wird. Sprich: Gibt es viele Finalizer, können die zu einem richtigen Performanceproblem werden.

Daher implementieren Klassen die einen Finalizer haben typischerweise IDisposable in dem typischen Stil wie man ihn immer wieder im MSDN findet. Falls der Programmierer Dispose aufruft, werden die gehaltenen Ressourcen sofort freigegeben und das Objekt wird so markiert, dass es nicht auf der Finalizerqueue landet. Falls der Programmierer das verschläft, wird irgendwann wohl der Finalizer zum Zuge kommen und dann halt die Ressourcen freigeben.

D.h. als Schlussfolgerung: Hält deine Klasse weder direkt noch indirekt solche Ressourcen, brauchst du IDisposable nicht zu implementieren.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

De_Struktor

unregistriert

5

18.05.2013, 14:13

und was ist mit den Texturen und meinen eigenen Klassen, wie kann ich denn erkennen, ob sie nicht mehr gebraucht werden bzw ob noch Referenzen auf sie liegen??

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

6

18.05.2013, 14:14

Na wenn es deine sind, dann weißt du doch wann du welche Textur nicht mehr brauchst.

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

7

18.05.2013, 14:20

und was ist mit den Texturen und meinen eigenen Klassen, wie kann ich denn erkennen, ob sie nicht mehr gebraucht werden bzw ob noch Referenzen auf sie liegen??


Als Faustregel würde ich sagen, wenn Felder deiner Klasse unmanaged Ressourcen, die z.B. per P/Invoke bekommen hast, oder Objekte, die disposable sind, halten, dann solltest du IDisposable implementieren. Ansonsten solltest du es nicht tun und dann brauchst du dir keine Gedanken darüber zu machen, ob es noch Referenzen auf die Objekte gibt.

Solltest du doch mal IDispoable brauchen, nun, dann ergibt sich das aus Programmablauf. Wie bei unmanaged Sprachen, wann man ein Objekt deleten kann.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

De_Struktor

unregistriert

8

18.05.2013, 18:50

Das bedeutet, ich muss in allen meinen 4 Klassen die "IDisposable" Schnittstellen implementieren.
Da ja alle meine 4 Klassen die unmanaged Ressource "Texture" aufweisen??

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

18.05.2013, 21:35

Bitte beachten, dass allein die Implementierung von IDisposable NICHT ausreichend ist, denn der Garbage-Collector ruft nicht von allein Dispose() auf. Das muss man explizit mit in den Destruktor rein schreiben. Anders verhält es sich natürlich bei der using-Direktive.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

De_Struktor

unregistriert

10

18.05.2013, 22:56

IDisposable

BC, noch ne kleine Frage, WO genau muss ich denn die using-Direktive implementieren??
also, die Speicherbereinigung mit using ist mir bekannt, jedoch weiss ich nicht, in welchm Part ich das machen muss.

Z.b, das Objekt myPlayer, welches in der Gameklasse in "Loadcontent", "Update" und "Draw" Methode Verweise aufweist, dann will ich, sobald all dies abgearbeitet ist, will ich das Objekt "zerstören".

Und anfangs habe ich mir gedacht, wenn ich F11 drücke, dann öffnet sich ja das Hauptprogramm, da wird ja:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;

namespace FrostBomber
{
#if WINDOWS || XBOX
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        ///

        static void Main(string[] args)
        {
            using (FrostBomber game = new FrostBomber())
            {
                game.Run();
            }
            
        }
    }
#endif
}

auch das Game objekt zerstört, sobald es beendet wird.

Und ich wollte Anfangs auch meine Klassen darein implementieren, das geht jedoch nicht^^, wie ich festgestellt habe und meine Frage jetzt ist, wo soll ich es implementieren, sobald die eben 3 genannten Methoden vorüber sind??

Mfg

De_Struktor

P.s wann weiss ich auch, wann eine Referenzierung vorüber ist?

Werbeanzeige