Getter 中的 VB.NET 调用 Setter
我有一个这样的类:
Public Class MyClass
Private _intList As New List(Of Integer)
Private _avg As Decimal
Public Sub Add(ByVal anInt As Integer)
_intList.Add(anInt)
End Sub
Public Property Avg() As Decimal
Get
Dim _sum As Integer = 0
For Each anInt In _intList
_sum += anInt
Next
Avg = If((_intList.Count > 0), _sum / _intList.Count, _avg)
Return _avg
End Get
Set(ByVal value As Decimal)
If _avg <> value Then
_avg = value
Console.WriteLine("Value changed")
End If
End Set
End Property
End Class
Getter 正在计算平均值并调用 Setter 来保存该值。由于某种原因我无法理解,平均值始终为 0。例如:
Dim c As New Class2()
c.Add(1)
c.Add(2)
c.Add(3)
Console.WriteLine(c.Avg.ToString()) ' This will print 0
我做错了什么吗?这是什么原因呢?
I have a class like this:
Public Class MyClass
Private _intList As New List(Of Integer)
Private _avg As Decimal
Public Sub Add(ByVal anInt As Integer)
_intList.Add(anInt)
End Sub
Public Property Avg() As Decimal
Get
Dim _sum As Integer = 0
For Each anInt In _intList
_sum += anInt
Next
Avg = If((_intList.Count > 0), _sum / _intList.Count, _avg)
Return _avg
End Get
Set(ByVal value As Decimal)
If _avg <> value Then
_avg = value
Console.WriteLine("Value changed")
End If
End Set
End Property
End Class
The Getter is calculating average and calls Setter to save the value. For some reason I cannot understand, the average is always 0. For example:
Dim c As New Class2()
c.Add(1)
c.Add(2)
c.Add(3)
Console.WriteLine(c.Avg.ToString()) ' This will print 0
Did I do something wrong? What is the cause of this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
哇,我想你已经发现了 VB 的一个非常奇怪的行为:当你在函数的定义中时,你可以使用
Return 返回一个值任一
或通过使用=
来“设置”函数的值。像这样:
在上面的函数中,
GetInteger = 5
行基本上相当于Return 5
*。好的,所以您可能已经知道了。但这是奇怪的部分,直到现在测试它之前我都不知道情况是这样的(诚然,在 Mono ,但我看到了与您相同的行为):显然这也适用于属性获取器。所以看看这一行:
您实际上没有在那里调用属性设置器;您正在为 getter 设置返回值。您可以通过删除行
Return _avg
; 来验证这一点突然你会看到你的 getter 开始返回实际的平均值。*不完全相同,因为您可以稍后将
GetInteger
设置为其他内容而不立即返回,而使用Return
可确保函数正确返回离开。Wow, I think you've discovered a very strange behavior of VB: when you are inside the definition of a function, you can return a value either with
Return
or by using=
to "set" the function's value.Like this:
In the above function, the line
GetInteger = 5
is basically equivalent toReturn 5
*.OK, so you probably already knew that. But here's the weird part, and I had no idea this was the case until testing it just now (admittedly, on Mono, but I am seeing the same behavior you are): apparently this applies to property getters as well. So look at this line:
You're actually not calling the property setter there; you're setting the return value for the getter. You can verify this by removing the line
Return _avg
; suddenly you will see your getter starts returning the actual average.*Not exactly the same, as you could later set
GetInteger
to something else without returning immediately whereas usingReturn
ensures the function returns right away.这是设计使然,并且在 Visual Basic 语言规范第 9.7.1 章中明确提到:
通过直接分配 _avg 字段来解决您的问题。最好避免具有此类副作用的属性获取器。
This is by design and explicitly mentioned in the Visual Basic Language Specification, chapter 9.7.1:
Solve your issue by assigning the _avg field directly. Property getters with side-effects like this is best avoided.
您的 setter 和 getter 实际上应该只返回属性,而不是自己进行计算。尝试创建一个像 calcAvg() 这样的方法来执行平均值计算,并在
Add()
上调用该方法(该方法在内部不应重新执行整个平均值计算,但如果您不确定如何执行此操作,请告诉我)。该calcAvg()
方法将设置_avg
实例变量。另外,我不确定它是否真的能让发送者拥有平均的二传手。数字的平均值是派生属性,不应该由外部用户设置。
Your setters and getters really should just be returning properties, and not doing the calculations themselves. Try creating a method like
calcAvg()
that does the average calculations, and on theAdd()
call that method (which should internally not re-perform the whole average calculation, but simply update it. Let me know if you're not sure how to do that). ThatcalcAvg()
method will set the_avg
instance variable.Also, I'm not sure it really makes send to have a setter for the average. An average of numbers is a derived property, not something that should be set by an external user.
MrDanA 的答案比我要给你的更正确,但是,我相信你得到 0 值的原因是因为你从未将变量 _avg 设置为任何值。进行 AVG 计算后,如果您这样做:
_avg = AVG
return _avg
当我这样做时,我得到的值为 2。
正如我之前所说,MrDanA 的答案是一个更好的方法。
MrDanA answer is more correct than what I'm going to give you, however, I believe the reason why you are getting the value of 0 is because you are never setting the variable _avg to anything. After you do your AVG calculation if you do:
_avg = AVG
return _avg
I get a value of 2 when I do this.
Like I said before though... MrDanA's answer is a better way to go.