问题描述
我阅读了Microsoft的带有声明的文档,但仍然不了解With
语句的目的是什么。
Xpost from Reddit,认为这确实应该在Stack Overflow上的某个位置,并且找不到任何这种性质的问题。
解决方法
With
简介
想象以下代码(示例A):
ThisWorkbook.Sheets(1).Range("A1").Font.Color = rgb(255,0)
ThisWorkbook.Sheets(1).Range("A1").Font.Bold = true
ThisWorkbook.Sheets(1).Range("A1").Font.Italic = true
ThisWorkbook.Sheets(1).Range("A1").Font.Size = 16
如果我们计算.
,则在此示例中有13个。这意味着通过属性访问器访问对象,这在我们的代码中为13次。
当我们改用With
语句时会发生什么? (示例B):
With ThisWorkbook.Sheets(1).Range("A1").Font
.Color = rgb(255,0)
.Bold = true
.Italic = true
.Size = 16
End With
如果我们在新代码中计算.
,我们会看到属性访问器仅被调用7次!因此,通过使用With
语句,我们仅使VBA要做的工作量减少了一半!
这是使用With
语句的主要好处。
内部运作方式
VBA内部正在执行以下操作(示例C):
Dim temp1 as Object
set temp1 = ThisWorkbook.Sheets(1).Range("A1").Font
temp1.Color = rgb(255,0)
temp1.Bold = true
temp1.Italic = true
temp1.Size = 16
set temp1 = nothing 'More specifically temp1 now calls IUnknown::release()
因此,您实际上可以使用此代码模仿With
的行为,但是With
使用“隐藏变量”,它不会污染您的局部变量范围,因此这是首选。
性能警告
关于性能,With
语句的使用方式可能会对性能造成损害,而不是带来性能优势。
1。 A
是局部变量
Dim A as SomeObject
set A = new SomeObject
With A
.B = 1
.C = 2
.D = 3
End With
在这种情况下,A是局部变量。如果我们进行转换:
Dim A as SomeObject
set A = new SomeObject
Dim temp1 as SomeObject 'Unnecessary call
set temp1 = A 'Unnecessary call
temp1.B = 1
temp1.C = 2
temp1.D = 3
set temp1 = nothing
我们看到代码中可能存在一些性能损失,因为需要定义和设置temp1。但是与性能访问者相比,性能下降相对可以忽略不计,因此不太可能引起注意。请注意,性能下降在很大程度上可以忽略不计,因为设置一个对象并不会传递整个对象,而是会传递指向该对象的指针,这是非常出色的。
PS:目前,这种性能下降只是假设的,我将确认这是否成立,或者编译器是否优化了性能。
2。 A
是成员变量
如果我们有一个包含以下代码的类:
Public A as object
Sub Test
With A
.B = 1
.C = 2
.D = 3
End With
End Sub
在这种情况下,A是成员/属性变量。因此实际上隐藏了一些信息。我们纠正一下:
Public A as object
Sub Test
With Me.A
.B = 1
.C = 2
.D = 3
End With
End Sub
啊,现在我们可以看到,通过使用With
,我们实际上节省了3个成员访问器调用:
Dim Temp1 as object
set Temp1 = Me.A
Temp1.B = 1
Temp1.C = 2
Temp1.D = 3
set temp1 = nothing
vs
Me.A.B = 1
Me.A.C = 2
Me.A.D = 3
最终,我要说的是VBA可能正在使用您看不见的隐藏变量,因此,实际上发生在后台的是特定于上下文的。在某些情况下,您所做的可能保证使用With
,而在其他情况下,则不然。如有疑问,请使用With
,因为改错会带来的性能好处远大于对性能的不利影响。
注意:With
语句在编写代码的速度和层次结构表示方面有一些小好处,但是这些主要是我个人的观点,不属于此处。
P代码和性能评估
如果有兴趣的话,下面是一些带有和不带有With
语句的示例的PCode转储。
当然,P代码只是故事的一半,因为不同的P代码操作将具有不同的速度。这是一个比较。
前3列显示一个测试,其中包含本文开头所述的3种情况。其余测试是相对随机的,但这是我学到的:
- with语句中的局部变量似乎比访问成员变量要快得多。
- 与一起使用会降低少量通话的性能。
- 按预期,
With A.O.O
的表现要好于A.O.O.Prop=...
- 与实际有明显的速度差异。因此,如果您可以尝试将
With
语句保留在任何循环之外!
注意:所有测试均在Excel 2011的Mac版本的VBA上运行
注意:所有测试都运行10 ^ 8次迭代-这意味着这些性能差异虽然很小,但是很小!