Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0346: Verwaltete Zeiger für .NET

 von 

Über den Tipp  

Dieser Tippvorschlag ist noch unbewertet.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Sonstiges
  • Sprachmerkmale

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
pointer, zeiger, ref, referenz, reference, managed, verwaltet, &, addressof, *, ptr, lambda, closure

Der Vorschlag wurde erstellt am: 13.02.2009 18:58.
Die letzte Aktualisierung erfolgte am 13.02.2009 18:58.

Zurück zur Übersicht

Beschreibung  

.NET unterstützt keine Zeiger - Zumeist ist das auch gar nicht erforderlich, sind doch alle Objekte ohnehin Referenzen und ByRef-Parameter an Funktionen erlaubt. In manchen Fällen kann es aber sinnvoll sein, einen solchen Parameter z.B. in einer Klasse zu speichern oder einer Klasse als Aktionsziel eine lokale Variable zu geben. Das ist mit .NET-Mitteln standardmäßig machbar, man müsste sich eine Wrapperklasse schreiben, mit der gerechnet wird und deren Wert am Ende zurückgeschrieben wird.

Über anonyme Funktionen kann dennoch ein Zeiger-Effekt erreicht werden. Die hier vorgestellte Pointer-Klasse hat nichts mit den C++- oder C#-Zeigern zu tun. Sie ist nicht unsicher und stellt keinen Hack dar, nichts muss gefixt werden, sondern sie agiert mit ganz normalen Objekten, die vom GC genauso betroffen sind. Erstellt werden muss sie mit der Syntax

New Pointer(Of <Typ>)(Function (p) p(<Ziel>))

p ist eine vom Zeiger übergebene Funktion, die auf das Ziel angewendet wird, wie z.B. eine zum Lesen oder Setzen des Wertes.
Dafür, dass dies korrekt abläuft, sorgt der Compiler selbst.

Schwierigkeitsgrad

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [8,90 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' --------- Anfang Projektgruppe ManagedPointers.sln ---------
' -------- Anfang Projektdatei ManagedPointers.vbproj --------
' ----------------- Anfang Datei Module1.vb  -----------------
Module Module1

    Class StringBuilder

        Public Destination As Pointer(Of String)

        Public Sub Append(ByVal Other As String)

            Destination.Value &= Other

        End Sub

    End Class

    Sub Main()

        Dim i As Integer = 42

        Console.WriteLine("i hat den Wert {0}", i)

        ' Zeiger erstellen
        Dim Pointer = New Pointer(Of Integer)(Function(p) p(i))

        i += 1
        Console.WriteLine("i hat den Wert {0}", Pointer.Value)

        Dim Pointer2 = Pointer

        Pointer2.Value *= 2
        Console.WriteLine("i hat den Wert {0}", i)

        ' Variable und Zeiger erstellen
        Dim MyString = "Hallo"
        Dim MyPtr = New Pointer(Of String)(Function(p) p(MyString))

        Dim Builder = New StringBuilder() With {.Destination = MyPtr}

        Call Builder.Append(", ")
        Call Builder.Append("Welt")

        Console.WriteLine("MyString: {0}", MyString)

        Console.ReadKey()

    End Sub

End Module

' ------------------ Ende Datei Module1.vb  ------------------
' ----------------- Anfang Datei Pointer.vb  -----------------
Option Strict On

Module Pointers

    ' Delegatenfunktionen
    Public Delegate Function ReferencAction(Of T)(ByRef Value As T) As Object
    Public Delegate Function PointerAccessor(Of T)(ByVal Action As ReferencAction(Of T)) As Object

    ''' <summary>
    ''' Verwalterer Zeiger
    ''' </summary>
    ''' <typeparam name="T">Typ der Werte</typeparam>
    <DebuggerStepThrough()> <DebuggerDisplay("{Value}")> Public Structure Pointer(Of T)

        ' Zugriffsfunktions
        Private m_Accessor As PointerAccessor(Of T)

        ' Lambda-Ausdrücke in Langform
        ' Closures für den Zugriff auf das Zeigerziel

        ' Abfrageclosure
        Private Class GetClosure

            Private m_Result As T

            Public ReadOnly Property Result() As T
                Get
                    Return m_Result

                End Get

            End Property

            Public Function Lambda(ByRef What As T) As Object

                m_Result = What

                Return Nothing

            End Function

        End Class

        ' Zuweisungsclosure
        Private Class SetClosure

            Private m_Value As T

            Public Sub New(ByVal Value As T)

                m_Value = Value

            End Sub

            Public Function Lambda(ByRef What As T) As Object

                What = m_Value

                Return Nothing

            End Function

        End Class

        ''' <summary>
        ''' Neuen Zeiger erstellen
        ''' </summary>
        ''' <param name="Accessor">Zugriffsausdruck der Form <example>Function(__) __(Ziel)</example></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal Accessor As PointerAccessor(Of T))

            m_Accessor = Accessor

        End Sub

        ''' <summary>
        ''' Zeigerziel setzen oder abfragen
        ''' </summary>
        ''' <value>Neuer Wert</value>
        ''' <returns>Aktueller Wert</returns>
        ''' <exception cref="ArgumentNullException">Zeigerziel ist ungültig</exception>
        Public Property Value() As T
            Get

                Dim Closure As New GetClosure

                Call m_Accessor.Invoke(AddressOf Closure.Lambda)

                Return Closure.Result

            End Get

            Set(ByVal value As T)

                Dim Closure As New SetClosure(value)

                Call m_Accessor.Invoke(AddressOf Closure.Lambda)

            End Set

        End Property

        ''' <summary>
        ''' Gibt an, ob der Zeiger ein Nullzeiger ist
        ''' </summary>
        Public ReadOnly Property IsNothing() As Boolean
            Get
                Return m_Accessor Is Nothing

            End Get

        End Property

        Public Shared Operator IsTrue(ByVal Pointer As Pointer(Of T)) As Boolean

            Return Not Pointer.IsNothing

        End Operator

        Public Shared Operator IsFalse(ByVal Pointer As Pointer(Of T)) As Boolean

            Return Pointer.IsNothing

        End Operator

    End Structure

End Module

' ------------------ Ende Datei Pointer.vb  ------------------
' --------- Ende Projektdatei ManagedPointers.vbproj ---------
' ---------- Ende Projektgruppe ManagedPointers.sln ----------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.
Folgende Diskussionen existieren bereits

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.