问题的背景
Visual Basic 中的属性允许封装获取和设置值的逻辑。引入属性后,代码变得更具可读性和安全性,消除了对类字段的直接访问需求,并简化了在对象中实现验证或计算逻辑。
问题
初学者常常将字段设为公共,或使用没有 getter/setter 的自动属性,这会导致封装的破坏或无法实现计算值。另一个问题是属性内部的递归调用,导致 StackOverflow。
解决方案
在 Visual Basic 中,声明一个私有字段,属性包括带有所需逻辑的 Get 和 Set 块。计算属性只使用 Get,返回基于私有字段的计算值。在 set 块中始终应访问私有字段,以避免无限递归。
代码示例:
Private _price As Decimal Private _quantity As Integer Public Property Total As Decimal Get Return _price * _quantity ' 计算属性 End Get End Property Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) If value < 0 Then Throw New ArgumentException("价格必须为正") _price = value End Set End Property
关键特点:
在 Set Price 中可以访问属性 Name 吗?如果它同样通过私有字段实现?
可以,如果在 Price 的 set 块中访问另一个属性(例如,Name),这是允许的,因为对不同私有字段的访问不会导致递归。应避免对自身的访问:在 Set Price 中调用 Price 将导致递归。
代码示例:
Public Property Name As String Get Return _name End Get Set(value As String) _name = value End Set End Property Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) If Name Is Nothing Then _name = "default" _price = value End Set End Property
如果在属性的 Get 块中再次调用该属性会发生什么?
这将导致无限递归和 StackOverflow。在 get 块中始终使用私有字段,否则属性将调用自身。
Public Property Amount As Decimal Get Return Amount ' 将导致无限递归 End Get Set(value As Decimal) _amount = value End Set End Property
是否可以声明仅用于写入的属性(WriteOnly),这有什么危险?
存在 WriteOnly 属性,但不推荐使用,因为对象失去了返回值的能力,这降低了可读性和可预测性。如果仅用于写入,最好重新考虑架构。
Private _secret As String Public WriteOnly Property Secret As String Set(value As String) _secret = value ' 可以写入,无法获取。 End Set End Property
程序员决定将 Price 字段设为公共并直接使用它,结果 Price 有时错误地变为负值。
优点:
缺点:
同事将 Price 替换为具有私有字段和 set 块中的验证的属性,这防止了不正确的值。
优点:
缺点: