在下面的代码中,当尝试从Cases
列表中删除项目时,代码在Setter中断开,索引超出范围。在VisualStudio 2017中运行调试器时,它成功通过Remove()
函数并删除最后一项,但在返回Main()
后,它将在Setter上中断,并且调用堆栈表明它来自Remove调用。示例代码如下:
Sub Main()
Dim Cases As Collection = New Collection()
Dim caseIndex As Integer = 2
Cases.Remove(Cases(caseIndex))
End Sub
Public Class Collection
Public WithEvents Cases As List(Of CaseClass)
Public Sub New()
Cases = New List(Of CaseClass)()
Cases.Add(New CaseClass)
Cases.Add(New CaseClass)
Cases.Add(New CaseClass)
End Sub
Default Public Property BeltCase(ByVal Index As Integer) As CaseClass
Get
Return Cases(Index)
End Get
Set(ByVal Value As CaseClass)
Cases(Index) = Value
End Set
End Property
Public Sub Remove(ByRef BeltCase As CaseClass)
Cases.Remove(BeltCase)
End Sub
End Class
Public Class CaseClass
Public test As Int16
End Class
调用堆栈:
TestingVBBug.exe!TestingVBBug.Module1.Collection.set_BeltCase(Integer Index,TestingVBBug.Module1.CaseClass Value)Line 25 Basic TestingVBBug.exe!TestingVBBug.Module1.Main()Line 6 Basic
那么我们为什么要经历塞特犬呢?为什么在我们退出删除功能后会发生这种情况?
答案 0 :(得分:2)
问题是由您的Remove()
方法引起的,也就是说,您有ByRef
参数(出于某种原因)。使用ByRef
时,对方法内参数所做的任何更改都必须反映到传递给方法的变量中。这通过将值重新分配原始变量来实现。
在你的情况下,它的工作原理如下:
Remove()
方法并将变量(Cases(caseIndex)
)传递给它。Remove()
方法内完成的,可能或可能不包括更改参数BeltCase
的值。BeltCase
的值会重新分配给最初传递给方法(即Cases(caseIndex)
)的变量。BeltCase
属性的setter会被Index = 2
调用,这会引发超出范围的异常,因为Cases(2)
不存在(是去除)。要确认,当您替换此行时,您可以看到此问题消失:
Cases.Remove(Cases(caseIndex))
..用:
Dim myCase As CaseClass = Cases(caseIndex)
Cases.Remove(myCase)
这样,您创建一个新变量,该变量引用相同的CaseClass
对象,最重要避免调用Collection.BeltClase
属性的setter。
但是,更好的解决方案是首先不要使用ByRef
,因为在这种情况下您似乎不需要它。因此,只需使用Public Sub Remove(ByVal BeltCase As CaseClass)
代替。
点击this question查看有关ByVal
和ByRef
的更多信息。
最后一件事,请不要给你的班级Collection
打电话,因为看到你的项目的任何人都会感到非常困惑。