VBA-With语句的目的是什么 1 A是局部变量 2 A是成员变量

问题描述

我阅读了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转储。

1 P-Code Data

当然,P代码只是故事的一半,因为不同的P代码操作将具有不同的速度。这是一个比较。

2. P-Code Timings

前3列显示一个测试,其中包含本文开头所述的3种情况。其余测试是相对随机的,但这是我学到的:

  • with语句中的局部变量似乎比访问成员变量要快得多。
  • 与一起使用会降低少量通话的性能。
  • 按预期,With A.O.O的表现要好于A.O.O.Prop=...
  • 与实际有明显的速度差异。因此,如果您可以尝试将With语句保留在任何循环之外!

注意:所有测试均在Excel 2011的Mac版本的VBA上运行

注意:所有测试都运行10 ^ 8次迭代-这意味着这些性能差异虽然很小,但是很小!