【问题标题】:Calling property Setter from within Getter does not execute Setter?从 Getter 中调用属性 Setter 不会执行 Setter?
【发布时间】:2019-07-03 13:21:19
【问题描述】:

我在一个类中有一个字符串属性。每当修改属性的值时,该属性的 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

当我在“Get”行使用断点运行调试时,您可以看到Value = _value & "BAR" 行不会导致setter 执行。相反,它只是修改内存中 Value 变量的值,而不是实际执行 Setter。

这是设计使然吗?如果有,有什么解释吗?

我可以调整我的代码或更改某处的设置以使我的 Setter 在从 Getter 调用时被执行吗?


PS,我知道我可以编写一个单独的函数来设置值并从 Getter 和 Setter 调用它。我发帖的原因是因为我想尽可能避免额外的开销。


编辑 2019 年 7 月 3 日 @ 上午 8:50 这类似于this question。该帖子上接受的答案确实回答了“这是设计使然,为什么?”的问题,但我不确定我是否理解。一些额外的解释将不胜感激。

此外,该帖子中的任何答案都没有回答我的问题的第二部分,“我可以调整我的代码以某种方式从 Getter 中调用 Setter 吗?”这是我发布新问题的主要原因。


编辑 2019 年 7 月 3 日 @ 上午 9:10 我在下面添加了一些更接近我的真实课程的内容,以说明我为什么这样做:

(注意:Attribute 对象是属于我正在为其编写此插件的软件的一类对象。我无法修改或继承它。因此,我正在编写“定义”用附加功能“扩展”它的类。)

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

简而言之,Getter 在尝试返回其值之前检查属性是否确实存在。如果没有,它会调用 Setter 来创建它。

Setter 完全负责设置 Attribute 的值,包括在不存在时使用指定值创建它。这实际上是非常复杂的(不止一行代码),所以我不想在另一种方法中复制它。我也不想为它创建一个单独的专用方法,除非从 Getter 调用 Setter 是不可能的。

【问题讨论】:

  • 那是一些设计糟糕的代码。那不应该是一个属性。
  • @jmcilhinney 你介意解释一下原因并建议我应该怎么做吗?
  • @AFriend,我看到了那个。起初,我不明白接受的答案是如何设计的。重读后,我想我有点明白了。但是,没有一个答案能回答我问题的第二部分,“我可以调整我的代码或更改某处的设置以使我的 Setter 在从 Getter 调用时被执行吗?”
  • “通过直接分配 _avg 字段来解决您的问题”在您的情况下,它将是 _value

标签: .net vb.net properties


【解决方案1】:

在赋值之前添加Me.,它会调用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

【讨论】:

  • 啊,当然!如此简单,并且完全符合我的需要。谢谢。
【解决方案2】:

我同意 jmc 的评论,这很糟糕。话虽如此,这应该可以解决您的问题。 类属性 私有_value As String = ""

Public Property Value As String
    Get
        Return Me._value & "BAR"
    End Get
    Set(setVal As String)
        ' Do important stuff.
        MsgBox("Doing important stuff!") 'what???????
        ' Set value.
        Me._value = setVal
    End Set
End Property

结束类

我添加了我。稍微澄清一下。

【讨论】:

  • djv 回答了我的问题,但我在原始帖子中添加了更接近我的实际课程的内容,以说明为什么仅设置私有变量不起作用。 (实际上,我得到的是一个单独对象的值,所以根本没有私有变量)。感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
相关资源
最近更新 更多