I have a string property within a class. The Setter for the property is supposed to do some important external operations whenever the property's value is modified.
In some circumstances, the Getter itself is supposed to modify the property's value before returning it. When it does this, I still want the important operations within the Setter to be executed.
However, whenever I have the Getter of my property attempt to change the property's value, the Setter is skipped altogether.
Below is some mock-up code that demonstrates what I'm seeing:
Sub Main()
Dim att As New Attribute
' The following line should "do important stuff"
' (and it does).
att.Value = "FOO"
' The following line sould add "BAR" to the end and "do important stuff"
' (it does neither).
Dim getValue As String = att.Value
MsgBox("Value: " & getValue)
End Sub
Class Attribute
Private _value As String = ""
Public Property Value As String
Get
' Modify value using Setter.
Value = _value & "BAR"
' Return value.
Return _value
End Get
Set(setVal As String)
' Do important stuff.
MsgBox("Doing important stuff!")
'...
' Set value.
_value = setVal
End Set
End Property
End Class
When I run debugging with a breakpoint on the "Get" line, you can see that the Value = _value & "BAR"
line does NOT cause the setter to execute. Instead, it just modifies the value of the Value variable in memory, rather than actually executing the Setter.
Is this by design? If so, any explanation as to why?
Can I tweak my code or change a setting somewhere to make my Setter be executed when called from the Getter?
PS, I'm aware I could write a separate function for setting the value and call that from both the Getter and the Setter. My reason for posting is because I want to avoid that extra overhead if possible.
EDIT 7/3/2019 @ 8:50 AM This is similar to this question. The accepted answer on that post does answer the question of "is this by design and why?", but I'm not sure I understand it. Some additional explanation would be appreciated.
In addition, none of the answers on that post answer the second part of my question, "Can I tweak my code to somehow call the Setter from within the Getter?" This was my main reason for posting a new question.
EDIT 7/3/2019 @ 9:10 AM I'm adding someting closer to my real class below to demonstrate why I'm doing it like this:
(Note: the Attribute object is a class of object that belongs to the software that I'm writing this add-in for. It's impossible for me to modify or inherit it. So instead I'm writing a "Definition" class that "extends" it with additional functionality.)
Class AttributeDefinition
Public AttributeName As String
Private AttributeSet As Inventor.AttributeSet
Sub New(AttributeName As String, AttributeSet As Inventor.AttributeSet)
Me.AttributeName = AttributeName
Me.AttributeSet = AttributeSet
If AttributeSet.NameIsUsed(AttributeName) Then
AttributeObject = AttributeSet.Item(AttributeName)
End If
End Sub
Private AttributeObject As Inventor.Attribute
Property Value() As String
Get
If AttributeObject Is Nothing Then
Value = ""
End If
Return AttributeObject.Value
End Get
Set(setVal As String)
If AttributeObject Is Nothing Then
' Create Attribute with empty string as value.
' (In actuality, this taks much more than just one line of code).
AttributeObject = AttributeSet.Add(AttributeName, Inventor.ValueTypeEnum.kStringType, setVal)
Else
AttributeObject.Value = setVal
End If
End Set
End Property
End Class
In short, the Getter checks if the Attribute actually exists before trying to return its value. If it doesn't, it calls the Setter to create it.
The Setter is fully responsible for setting the Attribute's value, including creating it with the specified value if it doesn't exist. This is actually very involved (more than one line of code), so I don't want to duplicate it in another method. I also don't want to create a separate dedicated method for it, unless calling the Setter from the Getter is impossible.
Just add Me.
before assigning Value and it will invoke the setter
Public Property Value As String
Get
' Modify value using Setter.
Me.Value = _value & "BAR"
' Return value.
Return _value
End Get
Set(setVal As String)
' Do important stuff.
MsgBox("Doing important stuff!")
'...
' Set value.
_value = setVal
End Set
End Property
Agh, of course! So simple, and does exactly what I needed. Thank you.