我有一个这样的课程:
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
我做错了什么吗?造成这种情况的原因是什么?
答案 0 :(得分:6)
哇,我认为你发现了VB的非常奇怪的行为:当你进入函数的定义时,你可以用{返回 的值 {1}} 或使用Return
“设置”函数的值。
像这样:
=
在上述函数中,行Function GetInteger() As Integer
GetInteger = 5
End Function
基本上等同于GetInteger = 5
*。
Return 5
你实际上没有在那里调用属性设置器;你正在为getter设置返回值。您可以通过删除第Avg = If((_intList.Count > 0), _sum / _intList.Count, _avg)
行来验证这一点;突然你会看到你的吸气剂开始返回实际的平均值。
* 完全相同,因为您可以稍后将Return _avg
设置为其他内容而不立即返回,而使用GetInteger
可确保函数立即返回。 /子>
答案 1 :(得分:4)
这是设计并在Visual Basic语言规范第9.7.1章中明确提到:
一个特殊的局部变量,在Get中隐式声明 存取主体的声明空间与属性同名, 表示属性的返回值。局部变量有 表达式中使用时的特殊名称解析语义。如果 局部变量用于需要表达式的上下文中 然后分类为方法组,例如调用表达式 名称解析为函数而不是局部变量。 例如:
ReadOnly Property F(i As Integer) As Integer
Get
If i = 0 Then
F = 1 ' Sets the return value.
Else
F = F(i - 1) ' Recursive call.
End If
End Get
End Property
直接指定_avg字段解决您的问题。最好避免使用像这样的副作用的财产获取者。
答案 2 :(得分:1)
你的setter和getter真的应该只返回属性,而不是自己进行计算。尝试创建一个像calcAvg()
那样执行平均计算的方法,并在Add()
调用该方法(这应该在内部不会重新执行整个平均计算,但只是更新它。请告诉我,如果你'我不知道该怎么做)。 calcAvg()
方法将设置_avg
实例变量。
另外,我不确定它是否真的让send有一个平均的setter。数字的平均值是派生属性,而不是应由外部用户设置的属性。
答案 3 :(得分:0)
MrDanA回答比我要给你的更正确,但是,我相信你得到0值的原因是因为你永远不会将变量_avg设置为任何东西。如果你这样做了AVG计算:
_avg = AVG return _avg
当我这样做时,我的值为2.
就像我之前说过的那样...... MrDanA的答案是一个更好的方法。