Tipp-Upload: VB.NET 0346: Verwaltete Zeiger für .NET
von Dario
Ü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.
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 |
Verwendete API-Aufrufe: |
Download: |
' 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.