Optimization 在VB6中,何时应使用With End With以及何时应使用普通对象引用?

Optimization 在VB6中,何时应使用With End With以及何时应使用普通对象引用?,optimization,syntax,vb6,Optimization,Syntax,Vb6,仔细阅读我正在维护的代码,我发现在某些地方使用了With-End With构造 With my_object .do_this() .do_that() .do_the_other() End With 有时更直接 my_object.do_this() my_object.do_that() my_object.do_the_other() 这两种形式之间有细微的区别吗?一般来说,我更喜欢哪一种 (我个人的观点是,我选择第二个,因为在第一个嵌套两到三次之后,它开始让

仔细阅读我正在维护的代码,我发现在某些地方使用了
With-End With
构造

With my_object
    .do_this()
    .do_that()
    .do_the_other()
End With
有时更直接

my_object.do_this()
my_object.do_that()
my_object.do_the_other()
这两种形式之间有细微的区别吗?一般来说,我更喜欢哪一种


(我个人的观点是,我选择第二个,因为在第一个嵌套两到三次之后,它开始让我头疼——这是一个充分的理由吗?

我只会使用第一个版本来设置属性值,比如C#中的初始化块。如果要调用方法等,则使用第二种形式。

如果对象引用实际上是更复杂的表达式,如属性getter或函数的返回值,则会有所不同

比较一下:

With MyObjectFactory.CreateMyObject()
    .do_this
    .do_that
    .WriteToDatabase
End With
针对明显不正确的情况:

MyObjectFactory.CreateMyObject().do_this
MyObjectFactory.CreateMyObject().do_that
MyObjectFactory.CreateMyObject().WriteToDatabase
在这种情况下,实际等效的方法是创建一个引用:

Dim myObject as MyObject
Set myObject = MyObjectFactory.CreateMyObject() 
myObject.do_this
myObject.do_that
myObject.WriteToDatabase

至于你是否应该和积木一起使用,这实际上是个人喜好的问题。和您一样,我肯定会发现许多嵌套的块令人困惑。这可能也是一个信号,表明该函数应该被分成多个函数。

贾斯汀是不正确的
With…End With
构造不仅仅是语法糖果,它还是一种性能技巧。当对象路径包含多个点(.)时,性能的提高非常明显,尤其是在循环和/或处理
类型
(结构)时

例如,此代码:

For x = 1 to my_object.Employee.Records.Count
    Debug.Print my_object.Employee.Records(x).ID
Next
将更快,因为:

For x = 1 to my_object.Employee.Records.Count
    With my_object.Employee.Records(x)
        Debug.Print .ID
    End With
Next
而且,正如@wqw所指出的,它可能会更快(取决于您需要访问的属性数量),因为它提供了最少的对象重新限定:

With my_object.Employee.Records
    For x = 1 to .Count
        Debug.Print Item(x).ID
    Next    
End With

试一试,你会发现不同之处。

新答案只是为了发布代码

请注意,无论是使用带缓存的匿名变量还是显式引用变量(或过程参数),对象缓存都不会总是达到预期效果。下面的dumpr和DumpRSII都执行相同的操作,打印RS中的所有值:

Option Explicit
'Add a reference to ADO 2.5 or later.

Private RS As ADODB.Recordset

Private Sub MakeRS()
    Dim I As Integer

    Set RS = New ADODB.Recordset
    With RS
        .CursorLocation = adUseClient
        .Fields.Append "SomeField", adInteger
        .Open
        For I = 1 To 10
            .AddNew Array(0), Array(I)
        Next
    End With
End Sub

Private Sub DumpRS()
    With RS.Fields(0)
        RS.MoveFirst
        Do Until RS.EOF
            Debug.Print .Value
            RS.MoveNext
        Loop
    End With
End Sub

Private Sub DumpRSII(ByVal Field As ADODB.Field)
    With RS
        .MoveFirst
        Do Until .EOF
            Debug.Print Field.Value
            .MoveNext
        Loop
    End With
End Sub

Private Sub Main()
    MakeRS
    DumpRS
    DumpRSII RS.Fields(0)
    RS.Close
End Sub

Field对象只是光标上的一个窗口。缓存字段对象可以显著提高按行重复ADO操作的性能。

我不相信“嵌套不好”的说法。您可以很容易地宣称嵌套如果块是一个标志,那么您应该分割过程。荒唐的缓存的匿名引用也不会花费任何费用,同时声明另一个引用变量对模块和项目符号总数的计数。这更多的是你对语言理解程度的问题,新手更喜欢对对象的每次使用进行超限定。@Bob-就我个人而言,我会对许多嵌套块(如OP所说,超过2或3个)感到困惑。嵌套的if语句也是如此——一旦嵌套太深,就开始变得混乱和难以重构。@Bob——很高兴知道引用变量计入符号总数——我从来没有想过会有限制。快速搜索显示大约有32k个符号()。毫无疑问,很快深度缩进就会成为一个问题。嵌套哪些块结构无关紧要:Ifs、Select Cases、With、Fors等。Justin,使用With..End With的主要目的是只进行一次对象重新鉴定,从而提高性能。查看我的答案。更像是使用my_object.Employee.Records
在循环外,然后
Debug.Print.Item(x.ID
在循环内你是说第一个还是第二个会更快?(对不起,我只是不确定“远快于”是指“远快于”还是“如果改为”则远快于”)。如果第二个更快,那确实很有趣——你知道为什么它更快吗?@Justin,第二个更快。