我觀察到VB.net中的一個行爲,在這個行爲中,屬性設置者被調用的次數似乎比看起來需要的多,並且調用了姐姐setter方法。爲什麼Property Setter會比預期更頻繁地被調用?
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Console.WriteLine("Calling WorkReferenceTypeByReference")
WorkReferenceTypeByReference(ReferenceTypeData)
Console.WriteLine("Called WorkReferenceTypeByReference")
Console.WriteLine("Calling WorkReferenceTypeByValue")
WorkReferenceTypeByValue(ReferenceTypeData)
Console.WriteLine("Called WorkReferenceTypeByValue")
End Sub
Public Sub WorkReferenceTypeByReference(ByRef ref As Point)
Dim b As Point = New Point(4, 4) + ref
Console.WriteLine(" adding (4,4) to " & ref.ToString)
End Sub
Public Sub WorkReferenceTypeByValue(ByVal ref As Point)
Dim b As Point = New Point(4, 4) + ref
Console.WriteLine(" adding (4,4) to " & ref.ToString)
End Sub
Private m_ReferenceType As Point = New Point(0, 0)
Public Property ReferenceTypeData As Point
Get
Console.WriteLine(" Calling ReferenceTypeData getter")
Console.WriteLine(" returning: " & m_ReferenceType.ToString)
Return m_ReferenceType
End Get
Set(ByVal value As Point)
Console.WriteLine(" Calling ReferenceTypeData setter")
Console.WriteLine(" value = " & value.ToString)
m_ReferenceType = value
End Set
End Property
End Class
前面的代碼返回到控制檯下面的輸出
Calling WorkReferenceTypeByReference
Calling ReferenceTypeData getter
returning: {X=0,Y=0}
adding (4,4) to {X=0,Y=0}
Calling ReferenceTypeData setter
value = {X=0,Y=0}
Called WorkReferenceTypeByReference
Calling WorkReferenceTypeByValue
Calling ReferenceTypeData getter
returning: {X=0,Y=0}
adding (4,4) to {X=0,Y=0}
Called WorkReferenceTypeByValue
注意方法執行下列虛假調用屬性setter。我認爲這種行爲是作爲一種安全措施產生的,以防止無意中修改基礎財產,儘管這可能是意圖。
ByRef vs ByVal使用情況下的這種行爲很容易通過選擇適當的ByVal關鍵字來解決,然而他們最近注意到了一個更危險的行爲,一個導致了重複調用的堆棧溢出,因爲setter調用會更新只有調用getter的值。
Public Sub DoSomething()
Dim a As New CustomObject(anotherObject.AProperty(getterArgument))
End Sub
Public Class AnotherObject
Public Property AProperty as SomeType
Get
' Get value
End Get
Set
' Set value, call DoSomething
End Set
End Property
End Class
在前面的例子中,主叫DoSomething的()將觸發AProperty吸氣劑的方法,但那時,在使用後,將火setter方法,其通過程序邏輯()再次調用DoSomething的。這是對二傳手的自動調用令我困惑。
使用Option Strict On編譯此代碼以查看問題。 –