konstruktor und destruktro

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    konstruktor und destruktro

    Hallo,

    kurze Frage,

    Wenn ich in einer Windows Form Anwendung oder in einem Modul eine Klasse verwende

    z.B.

    VB.NET-Quellcode

    1. dim variable as Klassexy
    2. vaiable = new Klassexy


    muss ich danach den Dynamisch reservierten Speicherbereich mit einem Destruktor wieder freigenben?

    Also so wie in C++ oder ist das in VB anders?
    Hi
    das übernimmt die Garbage Collection (GC) für dich. Sobald eine "Gruppe" von Objekten keine (nicht-schwache) Referenz mehr auf sich besitzt, wird sie als unbenutzt markiert und freigegeben, sofern der Benutzer nicht was anderes sagt.
    Hierzu folgenden Code:

    VB.NET-Quellcode

    1. Public Class SomeClass
    2. Public Property NextClass As SomeClass
    3. End Class

    Jetzt ergeben sich folgende Möglichkeiten:

    VB.NET-Quellcode

    1. Shared Sub X1()
    2. Dim x As New SomeClass() '(Standard-)Konstruktor wird aufgerufen
    3. End Sub 'keine Referenz mehr auf x ==> freigeben
    4. Shared Sub X2()
    5. Dim x As New SomeClass()
    6. x.NextClass = x 'Eine Referenz auf x wird hinzugefügt
    7. End Sub 'jetzt besteht eine Referenz auf x, aber die gesamte Gruppe wird freigegeben, da ja kein Element der Gruppe mehr von außen zugänglich ist
    8. Private Shared _reference As SomeClass
    9. Shared Sub X3()
    10. Dim x As New SomeClass()
    11. Dim y As New SomeClass()
    12. _reference = x
    13. End Sub 'y wird freigegeben, x nicht, da es in _reference gespeichert wird.

    Also gilt: Wenn kein Verweis mehr auf ein Objekt existiert, wird es freigegeben, da man ja nicht mehr auf es zugreifen kann. Solange es innerhalb des Programms jemandem bekannt ist, wird es benötigt und darf nicht freigegeben werden.

    Ausnahme hierbei sind sog. WeakReference-Objekte, spezieller geht es auch über ein System.Runtime.InteropServices.GCHandle, wenn du es dir genauer anschauen willst.

    Gruß
    ~blaze~
    Hey,
    New legt in VB.Net nichts auf den Heap, genauso wenig hat man Pointer. Es erstellt eine Instanz der Klasse. Für gewöhnlich gibt man Speicher, aber im Dispose() wieder frei, dafür implementierst du einfachIDisposeable. Das macht man eigentlich nicht im Finalizer

    Gonger96 schrieb:

    New legt in VB.Net nichts auf den Heap

    Natürlich wird das auf den Heap gelegt. (Bei Klassen, Strukturen werden auf dem Stack abgelegt) Wohin denn sonst? Eine hauptaufgabe des Garbage Collectors ist es z.B. auch, Objekte nach letzem Zugriff im Heap umzusortieren.
    Dispose wird dazu verwendet, unverwaltete Ressourcen freizugeben, verwaltete werden nicht automatisch freigegeben (aber man setzt meist die Referenzen auf verwaltete Objekte auf Nothing. Unverwaltete Ressourcen sind eben solche, die nicht von der GC verwaltet werden. In .Net wird afaik eine einem Heap ähnelnde Speicherverwaltung verwendet, die auch Speicherblöcke verschiebt, etc., was eigentlich nicht Aufgabe eines Heaps ist.
    @Gonger96: Objekte können auch angepinnt werden (siehe System.Runtime.InteropServices.GCHandle.Allocate bzw. fixed in C#), dann hast du deinen Zeiger, sofern der Typ der Instanz ein sequentielles Layout hat.

    Gruß
    ~blaze~
    Nö, das kommt aufn CLR-Heap. In C++/CLI kann man das ganz schön sehen, per gcnew kommts aufn CLR-Heap und per new auf den nicht Verwalteten. Das gilt aber auch nur für Referenzklassen, Valueklassen und Structures kommen auch per New auf den Stack.

    @~blaze~
    Joa, den eigentlichen Pointer kriegt man ja nur in C#. Für P/Invoke ists aber unerlässlig stimmt.
    @Gonger96: Wenn du die über GCHandle anpinnst, kommst du über System.Runtime.InteropServices.GCHandle.Alloc(object, Runtime.InteropServices.GCHandleType.Pinned):

    VB.NET-Quellcode

    1. Dim v As Integer = 123
    2. Dim p As Object = v
    3. Dim gch = System.Runtime.InteropServices.GCHandle.Alloc(p, Runtime.InteropServices.GCHandleType.Pinned)
    4. System.Runtime.InteropServices.Marshal.WriteInt32(gch.AddrOfPinnedObject(), 321)
    5. gch.Free()
    6. v = DirectCast(p, Integer)
    7. MessageBox.Show(v.ToString())

    auch in VB. Einziger Unterschied ist, dass man in VB wohl nicht auf die Adresse von Structures kommt, da die ja auf dem Stapel liegen, außer man boxt sie, wie oben. Da bekommt man dann aber eben auch die Adresse im Heap, nicht die vom Stack.

    Bzgl. CLR-Heap und Heap: Das war das, was ich mehr oder weniger meinte. Die CLR verwendet ja eine art VM, um daher hat es wohl auch seine eigene Implementation. Da die Speicherverwaltung nicht der des Betriebssystems entspricht, muss es halt auch mehr oder weniger eine eigene Speicherverwaltung auf Basis von festen Memoryblöcken vornehmen, weil das Umkopieren von Memoryblöcken auf Betriebssystemebene vmtl. nicht auf diese Art der Verwaltung optimiert ist, weiß ich aber nicht sicher.

    Gruß
    ~blaze~
    In VB bekomm ich so "nur" einen IntPtr zurück. Die hält ja nur einen Pointer, an den würd ich ja in C# per IntPtr.GetPointer() kommen und mir wird ein Pointer vom Typ void* bekommen. In VB bekomm ich den nicht (glaub ich zumindest, hab' momentan keine IDE zur Verfügung).

    Gruß