pen.Dispose() vs Pens.Yellow.Dispose()

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    pen.Dispose() vs Pens.Yellow.Dispose()

    Ich denke, der Titel sagt schon alles.
    Zur Darstellung und Beschriftung von Messkurven habe ich eine Klasse, der ein Pen übergeben wird (analog andere IDisposable Objekte).
    Beim finalen Aufräumen müssen diese Objekte zerstört werden.
    Nun kommt es vor, dass neben einem New Pen(Color.Red, 2) auch ein Pens.Yellow übergeben wird.
    Ersterer kann disposed werden, bei letzterem kommt eine ArgumentException.
    Frage:
    Gibt es eine einfache Abfrage, ob ein derartiges Objekt dynamisch oder statisch erzeugt wurde?
    oder
    Ist hier ein Try/Catch im Dispose() die einzige Möglichkeit, das abzufangen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Grundsatzfrage:
    Warum räumst du die denn auf? Die liegen, nach meinem Verständnis, nicht in deiner Hoheit. Der der den Pen erstellt, ist dafür verantwortlich ihn wieder weg zu räumen.

    Zu deiner Frage:
    So weit ich weiß, in der Situation nicht.
    Guten Morgen,

    diese Grundsatzfrage interessiert mich auch gerade sehr.
    Was genau liegt denn in der Hoheit des Programmierers? Ich habe mich belesen und gelernt das der Garbage Collektor recht gut auf den verwendeten Speicher aufpasst. Leider geht nirgends genau hervor was man selber aufräumen bzw. freigeben muss; was also "unmanaged Code" ist...

    Der Satz "Der der den Pen erstellt, ist dafür verantwortlich ihn wieder weg zu räumen." ist gut, aber es bleibt die Frage: Wann, wo und wie mache ich das am sinnvollsten?

    slice schrieb:

    Grundsatzfrage:

    VB.NET-Quellcode

    1. MyObject1 = New OwnObjectClass(New Pen(Color.Red, 2))
    2. MyObject2 = New OwnObjectClass(Pens.Yellow)
    3. ' ...
    4. MyObject1.Dispose()
    5. MyObject2.Dispose()

    VB.NET-Quellcode

    1. Class OwnObjectClass
    2. Inherits IDisposable
    3. Private myPen As Pen
    4. Public Sub New(p As Pen)
    5. Me.myPen = p
    6. End Sub
    7. Public Sub Dispose()
    8. Me.myPen.Dispose()
    9. End Sub
    10. End Class

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Da würde ich den Konstruktor so umbauen, das er als ersten Parameter eine Farbe, als zweiten (Optional) die Breite annimmt und dann in "OwnObjectClass" den Pen erstellen. Damit ist sichergestellt das er "richtig" erstellt wird und nicht von außen während deiner Benutzung Disposed wird.

    VB.NET-Quellcode

    1. Class OwnObjectClass
    2. Inherits IDisposable
    3. Private myPen As Pen
    4. Public Sub New(color As Color)
    5. Me.New(color, 1)
    6. End Sub
    7. Public Sub New(color As Color, width As Single)
    8. Me.myPen = New Pen(color, width)
    9. End Sub
    10. Public Sub Dispose()
    11. Me.myPen.Dispose()
    12. End Sub
    13. End Class


    @Snake3000 Das mit dem GC etc. ist nochmal ein ganz eigenes Thema, da bin ich auch nicht so tief drin. Ich räume das weg was ich erstelle, alles andere ist nicht meine Sache.
    Erstell ich zb. den Pen, räume ich ihn am Ende, wenn mein Code vorbei ist und ich ihn nicht mehr brauche weg. Wird der Pen meinem Code als Parameter übergeben, gehört er nicht mir, also räume ich ihn nicht weg.
    Danke Dir.

    Als absoluter Neuling in oops nehme ich mal mit, das ich alles was ich mit "new" constructed habe auch wegräumen muss? hmmmmmm……..
    Speicherverwaltung ist in jeder Sprache anders.

    In der .NET Welt hast du den GarbageCollector (GC), der sich um 95% aller Allokationen bzw. Aufräumarbeiten kümmert. Die restlichen 5% Implementieren IDisposable bzw. bieten die Methode .Dispose() an. Kurz gesagt bedeutet die Implementierung von IDisposable, dass diese Klasse ein Objekt beinhaltet, dass vom GC nicht ohne weiteres aufgeräumt werden kann/darf. Mit .Dispose() wird dem GC signalisisert, dass dieser nun dieses Objekt aufräumen darf.
    Ich muss jetzt doof fragen!, Kannst du Pens.Yellow noch verwenden nach Dispose() oder ist er jetzt g, wie ganz weg ? Oo

    *update

    Wenn ich mir die Source anschaue wird es komisch

    C#-Quellcode

    1. /// <include file='doc\Pens.uex' path='docs/doc[@for="Pens.Yellow"]/*' />
    2. /// <devdoc>
    3. /// <para>[To be supplied.]</para>
    4. /// </devdoc>
    5. public static Pen Yellow {
    6. [ResourceExposure(ResourceScope.Process)]
    7. [ResourceConsumption(ResourceScope.Process | ResourceScope.AppDomain, ResourceScope.Process | ResourceScope.AppDomain)]
    8. get {
    9. Pen yellow = (Pen)SafeNativeMethods.Gdip.ThreadData[YellowKey];
    10. if (yellow == null) {
    11. yellow = new Pen(Color.Yellow, true);
    12. SafeNativeMethods.Gdip.ThreadData[YellowKey] = yellow;
    13. }
    14. return yellow;
    15. }
    16. }
    Ist schon witzig das man sich zu Gigabyte Zeiten wieder um Speicherplatz kümmern muss....

    .Dispose() ist klar... sagt dem GC das es weg kann. Aber woher weiss ich das ich es disposen kann?
    Ist ne dumme Frage, aber die müssen auch gestellt werden...

    Snake3000 schrieb:

    das man sich zu Gigabyte Zeiten wieder um Speicherplatz kümmern muss....
    Wenn Du einen dynamischen Überwachungsprozess an einer Maschine hast, wo im Sekundentakt ca. 100 IDisposable Objekte erstellt werden, läuft der Speicher langsam aber sicher zu.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Snake3000
    Das dürfte auch interessant für Dich sein: Was sind verwaltete / nicht verwaltete Ressourcen

    @RodFromGermany
    Ich glaube beim StreamWriter/Reader gibt es das Konzept, dass im Konstruktor (die Überladung, die einen BaseStream annimmt) angegeben werden kann, ob der BaseStream ebenfalls disposed werden soll, wenn der StreamWriter/Reader disposed wird. Das wäre also eine Option.
    In diesem konkreten Fall wäre es aber sinnvoll, alle Pens, die im Konstruktor ankommen, zu klonen. Pen implementiert IClonable. Dieses Objekt darfst Du dann in jedem Fall disposen.
    Ansonsten gilt generell, dass man nur das disposed, was man auch selbst erstellt hat. Das heißt, den Pen, den Du in deine eigene Klasse gibst, disposed Du außerhalb dieser Klasse (wenn es ein selbst erstellter Pen ist), oder eben nicht. In der Klasse disposed Du den geklonten Pen.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Niko Ortner schrieb:

    ob der BaseStream ebenfalls disposed werden soll, wenn der StreamWriter/Reader disposed wird.
    Nö.
    Ich komme darauf, weil ich den Code meines Vorgängers einer Codeanalyse unterzogen habe.
    Da fielen die Pens auf und auch FileStream(Stream).
    Für diesen Fall schlägt Microsoft dieses Herangehen vor:

    C#-Quellcode

    1. Stream stream = null;
    2. try
    3. {
    4. stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    5. using (StreamWriter writer = new StreamWriter(stream))
    6. {
    7. stream = null;
    8. // Use the writer object...
    9. }
    10. }
    11. finally
    12. {
    13. if(stream != null)
    14. {
    15. stream.Dispose();
    16. }
    17. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hier hab ich ihn: msdn.microsoft.com/de-de/library/gg712952(v=vs.110).aspx
    Ist der leaveOpen-Parameter auf True gesetzt, bleibt der stream offen. So meinte ich das.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Niko Ortner OK, dann war das eine Mistverständnissung.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Ist hier ein Try/Catch im Dispose() die einzige Möglichkeit, das abzufangen?
    Jo - seh ich auch nix anneres.
    Interessanterweise kann man im Haltepunkt sehen, dass Pen ein privates Feld immutable As Boolean hat - also der Pen selbst weiss, ob er ein System-Pen ist oder nicht. Aber von aussen findet man das wohl nur durch Reflection oder Exception heraus.
    @ErfinderDesRades Try/Catch im Dispose() ist nach meinem Dafürgalten ein NoGo, deswegen dieser Thread.
    Das ganze ist offensichtlich ein Fehldesign meines Vorgängers, ich werde es auflösen, wie es @slice vorgeschlagen hat.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    nach meinem Dafürhalten ein NoGo
    nach meim nicht. Der Catch frisst keine Resourcen und das Ignorieren des Fehlers ist eine sichere Behandlung.
    Sieht bisserl bescheuert aus - aber ist ja nicht deine Schuld.

    Imo ein Fehldesign von MS, die hätten die SystemPens iwie anners designen müssen.

    Aber deine Alternative ist ja auch durchaus gangbar.

    slice schrieb:

    Public Sub New(color As Color)
    Me.New(color, 1)
    End Sub
    Public Sub New(color As Color, width As Single)
    Me.myPen = New Pen(color, width)
    End Sub

    Ich nehme da ganz gerne Optional anstatt einer Überladung.

    VB.NET-Quellcode

    1. ​Public Sub New(color As Color, Optional width As Single = 1)
    2. Me.myPen = New Pen(color, width)
    3. End Sub
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    @petaod Das hab ich schon so angedacht, es kommen momentan nur die Stärken 1 und 2 vor.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!