Zuverlässigen Weg, um pass Object-variable Methode, die erwartet, dass Objekt-parameter

Den normal erwarteten Semantik eines Referenz-Typ ist, dass er sich Verhalten sollte, wie eine Objekt-id. Wenn einige Variablen einen Verweis auf das 5483rd Objekt ein Programm erstellt, übergabe der variable an eine Methode geben sollte einen Verweis auf die 5483rd Objekt. VB.NET funktioniert auch meistens, wie diese, aber mit einer eher seltsamen Ausnahme: auch in der Option Strict On Dialekt, Versuch passieren solche eine variable vom Typ Object um eine Methode, die einen parameter von diesem Typ, kopieren Sie eine Object Variablen zu einer anderen, oder sonst eine "rvalue" des Typs Object [zu leihen C-Terminologie] gespeichert werden, um ein "lvalue" von dieser Art ist, wird manchmal dazu führen, dass der compiler das speichern einer Referenz auf ein anderes Objekt.

Ist es eine schöne Möglichkeit dies zu vermeiden in Fällen, in denen der code nicht kennen, und sollten sich nicht zu kümmern, über die Art der Objekte, der Umgang mit?

Wenn man entweder von den beteiligten Operanden werden von einem anderen Typ als Object, ist es kein problem. Innerhalb eine generische Methode, Variablen des generischen Typ wird auch korrekt arbeiten, selbst wenn es das geben geschieht Object. Parameter, die von der generische Typ, allerdings, wird so behandelt, als Object wenn der Typ aufgerufen wird, wird die Verwendung dieses Typs.

Sollten die Methoden:

Function MakeNewWeakReference(Obj As Object) As WeakReference
   Return New WeakReference(Obj)
End Function 

Function GetWeakReferenceTargetOrDefault(WR as WeakReference, DefaultValue as Object) _
     As Object
   Dim WasTarget as Object = WR.Target
   If WasTarget IsNot Nothing Then Return WasTarget
   Return DefaultValue
End Function

Würde man erwarten, dass die erste Funktion zurückkehren würde, WeakReference, dass lebendig bleibt, solange das übergebene Objekt ist. Man würde erwarten, dass, wenn die zweite Funktion ist gegeben, WeakReference, die noch am Leben ist, die Methode liefert eine Referenz, die würde lebendig zu halten. Leider ist diese Annahme schlägt fehl, wenn die Referenz bezieht sich auf eine Box mit nicht-primitiven Wert geben. In diesem Fall ist die erste Methode liefert eine schwache Referenz, um eine neue Kopie der boxed-Wert, nicht am Leben gehalten werden, indem die original-Referenz, und das zweite gibt eine neue Kopie der boxed-Wert, der wird nicht halten, die man in der schwachen Referenz lebendig.

Wenn man sich die Methoden generisch sein:

Function MakeNewWeakReference(Of T As Class)(Obj As T) As WeakReference
   Return New WeakReference(Obj)
End Function 

Function GetWeakReferenceTargetOrDefault(Of T As Class)(WR as WeakReference, _
             DefaultValue as T) As T
   Dim WasTarget as T = TryCast(WR.Target, T)
   If WasTarget IsNot Nothing Then Return WasTarget
   Return DefaultValue
End Function

dass würde das problem vermeiden innerhalb der Methoden, auch wenn man zum aufrufen MakeNewWeakReference(Of Object) oder GetWeakReferenceTargetOrDefault(Of Object). Leider, wenn man versucht, mit einer Methode mit einem parameter vom Typ Object, und entweder das Ding gespeichert werden (im ersten Fall) oder die variable wird gespeichert (in der zweiten) war auch Object würde das problem noch immer auftreten, bei der Methode invocation oder wenn die Speicherung seiner Rückkehr Wert. Wenn man alle der code in einer generischen Klasse, und immer nur verwendet es mit einem parameter vom Typ des Objekts, aber sicher immer TryCast Dinge geben Object zu dem generischen Typ (eine solche operation sollten eigentlich nie fehl, wenn der generische Typ passiert Object), die funktionieren würde, um das problem zu lösen, wäre aber ziemlich hässlich. Gibt es eine saubere Möglichkeit, um anzugeben, dass eine variable erlaubt sein sollte, um einen Verweis auf jede Art von heap-Objekt den Weg Object können, sollte aber immer so Verhalten, mit Referenz-Semantik die Art, wie alle anderen Referenz-Typen zu tun?

BTW, einige direkt ausführbarer Testcode:

Sub ObjTest(O1 As Object)
    Debug.Print("Testing type {0} (value is {1})", O1.GetType, O1)
    Dim O2 As Object
    Dim wr As New WeakReference(O1)

    O2 = O1 ' source and destination are type Object--not identity preserving

    Debug.Print("Ref-equality after assignment: {0}", O2 Is O1)
    Debug.Print("Ref-equality with itself: {0}", Object.ReferenceEquals(O1, O1))
    GC.Collect()
    Debug.Print("Weak reference still alive? {0}", wr.IsAlive)
    Debug.Print("Value was {0}", O1) ' Ensure O1 is still alive
End Sub

Sub ObjTest()
    ObjTest("Hey")
    ObjTest(1)
    ObjTest(1D)
End Sub

Gibt es keinen wirklichen Grund, warum die Art von Objekt, um die ObjTest(Object) Methode sollte darauf achten, welche Art von Objekt es gegeben, aber alle drei tests, die drucken true mit einer Klasse-Objekt wie String oder einen primitiven Wert geben wie Int32 scheitern mit einem nicht-primitiven Wert geben wie Decimal. Gibt es eine schöne Möglichkeit, dass zu beheben?

InformationsquelleAutor supercat | 2013-08-01
Schreibe einen Kommentar