为什么 VBA 编译器要求 For Each 迭代器的类型为 Variant?
例如,这段代码会抛出错误:
Public Sub IterationTest()
Dim arr(1 To 4) As String
Dim str As String
arr(1) = "A"
arr(2) = "B"
arr(3) = "C"
arr(4) = "D"
For Each str In arr
Debug.Print str
Next
End Sub
而这个不会:
Public Sub IterationTest()
Dim arr(1 To 4) As String
Dim str As Variant
arr(1) = "A"
arr(2) = "B"
arr(3) = "C"
arr(4) = "D"
For Each str In arr
Debug.Print str
Next
End Sub
强制使用Variant(或Object)类型没有多大意义。当编译时未知变量的确切类型时,应(稀疏)使用 Variant,而 For Each 的大多数使用情况并非如此。在大多数情况下,您可以知道要迭代的类型,并且可以简单地将迭代器设置为这种类型。
此外,一个集合中不可能包含不同类型的数据类型。在循环的每次迭代中,您将始终迭代相同的类型。字符串不会突然变成布尔值,这证明了使用像 Variant 这样的灵活类型是合理的。那么为什么不允许迭代器是强类型的呢?
这对我来说是一个问题,因为 Variant 是最耗内存的类型,但编译器强制您在每个 For Each 循环中使用它,即使它很容易被省略。微软似乎忽视了这一点。
首先,你所说的一般不属实...
这是真的仅适用于集合和数组。为什么?因为集合和数组可以保存各种元素(字符串、数字、对象等)。
Variant
声明(因此,它比其他类型需要更多的内存)必须替换任何可能的元素类型。
在下一个代码示例中,您可以使用适当的类型声明看到此类迭代:
Sub IteratorDeclaration()
Dim wb As Workbook
For Each wb In Workbooks
Debug.Print wb.name
Next wb
Dim ctrl As MSForms.Control
For Each ctrl In UserForm1.Controls
Debug.Print ctrl.name
Next ctrl
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
Debug.Print ws.name
Next ws
Dim txtB As TextBox 'for sheet Form text boxes...
For Each txtB In ActiveSheet.TextBoxes
Debug.Print txtB.name
Next txtB
Dim myArr, myEl 'declared implicitele as Variant
myArr = Split("a,b,c,d,e,f", ",")
For Each myEl In myArr
Debug.Print myEl
Next myEl
'and the most eloquent exammple:
Dim myCol As New Collection, Iterator
myCol.Add ActiveSheet
myCol.Add 10
myCol.Add "my text"
For Each Iterator In myCol
Debug.Print TypeName(Iterator)
Next Iterator
End Sub