VBA - 为什么 For Each 迭代器需要变体

问题描述 投票:0回答:1

为什么 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 循环中使用它,即使它很容易被省略。微软似乎忽视了这一点。

excel vba performance foreach variant
1个回答
0
投票

首先,你所说的一般不属实...

这是真的仅适用于集合和数组。为什么?因为集合和数组可以保存各种元素(字符串、数字、对象等)。

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
© www.soinside.com 2019 - 2024. All rights reserved.