温馨提示:本文翻译自stackoverflow.com,查看原文请点击:.net - Calling property Setter from within Getter does not execute Setter?
.net properties vb.net

.net - 从Getter内部调用属性Setter不会执行Setter吗?

发布于 2020-03-27 10:56:09

我在一个类中有一个字符串属性。每当修改属性值时,该属性的Setter都应该执行一些重要的外部操作。

在某些情况下,Getter本身应该在返回属性之前修改属性的值。当执行此操作时,我仍然希望执行Setter中的重要操作。

但是,每当我尝试使用属性的Getter来更改属性的值时,Setter都会被完全跳过。

下面是一些模拟代码,演示了我所看到的:

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.

查看更多

查看更多

提问者
DRoam
被浏览
156
djv 2019-07-03 22:21

只需Me.在赋值之前添加,它将调用设置器

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

在此处输入图片说明