Early & Late Binding

Mile-O

Back once again...
Local time
Today, 17:52
Joined
Dec 10, 2002
Messages
11,310
I see so many people using the ! notation over the . notation (i.e. Me!txtBox over Me.txtBox) and was wondering where everyone gets the 'instinct' to use the late binding (!) notation.

I understand that it has its benefits but early binding (.) and it's ability to ensure disambiguation and speed up code is so much better.

Where does this ! trend stem from?
 
I think Microsoft is itself responsible for the ! notation in it's documentation. When I first learned Access, it was the common notation, so I used it.

One article I read on MSDN suggests that the ! operator is best to use when you know the name of the object being referenced, as in Forms!MyForm, but if you don't know the name of the particular form, like when you're working with a variable form name, you should use Forms(strFormName) notation. Here is the article: Microsoft Access 2000: Building Applications with Forms and Reports.

I've also only seen the ! in relation to Access. I've never seen it mentioned in articles pertaining to Excel, for example though the notation works there as well.
 
In general, the rule of thumb I use is to move my thumb before I swing the hammer.... oh, wait! Wrong forum.

The way I learned this has to do with whether there is any variability in the thing being referenced.

For instance, let's take a control that can be visible or not. The property is Visible and you have no control over that name, so you use the . (I guess because there is nothing dynamic and the binding issue is moot - same result either way). But if you created it or if there is a dynamic component, you might wish to use the ! instead of the .

Also, oddly enough, there are times when you think either one would work, but 'tain't so.

A long time ago, back in the DBW (days before Windows), I used to use Paradox for DOS. It had both flavors of object selection and there were some bizarre rules about which one was used for which thing. I believe properties were ALWAYS dot (.) and field names in SQL were always bang (!). Did I just give away my age by revealing that little tid-bit? And old DEC Datatrieve also used the dot and bang notation for various elements in databases. On the other hand, old ShareBase databases didn't seem to care.
 
Control Objects

!; Implicitly refer to the control
.; Explicitly refer to the control

! is faster

Have a great day!
________
Ferrari F50 Gt
 
Last edited:
Code:
Option Explicit
Option Compare Text

Public Declare Function timeGetTime Lib "Winmm.dll" () As Long

[color=green]'   For DAO recordsets...
'
'   The ! appears to be 5% faster than the .
'   Both seem to be swamped out by the Edit and Update.
'
'   Tested on 64280 records
'[/color]
Sub Test1()
    Dim lngStart      As Long
    Dim rstLocalities As DAO.Recordset
    
    lngStart = timeGetTime()
    
    Set rstLocalities = CurrentDb.OpenRecordset("tblLocalities", dbOpenDynaset)
    
    Do Until rstLocalities.EOF
        rstLocalities.MoveNext
    Loop
    
    Set rstLocalities = Nothing
    
    MsgBox timeGetTime() - lngStart   [color=green]'  141 milliseconds[/color]

End Sub


Sub Test2()
    Dim lngStart      As Long
    Dim rstLocalities As DAO.Recordset
    
    lngStart = timeGetTime()
    
    Set rstLocalities = CurrentDb.OpenRecordset("tblLocalities", dbOpenDynaset)
    
    Do Until rstLocalities.EOF
        rstLocalities.Edit
        rstLocalities.Update
        rstLocalities.MoveNext
    Loop
    
    Set rstLocalities = Nothing
    
    MsgBox timeGetTime() - lngStart  [color=green]'  2995 milliseconds[/color]

End Sub


Sub Test3()
    Dim lngStart      As Long
    Dim rstLocalities As DAO.Recordset
    
    lngStart = timeGetTime()
    
    Set rstLocalities = CurrentDb.OpenRecordset("tblLocalities", dbOpenDynaset)
    
    Do Until rstLocalities.EOF
        rstLocalities.Edit
        rstLocalities!TestText = "ABC_"
        rstLocalities.Update
        rstLocalities.MoveNext
    Loop
    
    Set rstLocalities = Nothing
    
    MsgBox timeGetTime() - lngStart  [color=green]'  3195 milliseconds[/color]

End Sub


Sub Test4()
    Dim lngStart      As Long
    Dim rstLocalities As DAO.Recordset
    
    lngStart = timeGetTime()
    
    Set rstLocalities = CurrentDb.OpenRecordset("tblLocalities", dbOpenDynaset)
    
    Do Until rstLocalities.EOF
        rstLocalities.Edit
        rstLocalities.Fields("TestText") = "ABC_"
        rstLocalities.Update
        rstLocalities.MoveNext
    Loop
    
    Set rstLocalities = Nothing
    
    MsgBox timeGetTime() - lngStart  [color=green]'  3205 milliseconds[/color]

End Sub
[color=green]'
'   For what it is worth, those are the times I got.
'
'   Regards,
'   Chris.[/color]
 
Just my view but I disagree.

In my view 5% is not worth thinking about and I try to write source code for clarity, hell I might even have to come back and read it someday.

To me: -

rstLocalities.Edit
rstLocalities!TestText = "ABC_"
rstLocalities.Update
rstLocalities.MoveNext

reads better than: -

rstLocalities.Edit
rstLocalities.Fields("TestText") = "ABC_"
rstLocalities.Update
rstLocalities.MoveNext

because of the difference between the . and the ! i.e. three properties as opposed to one field.
(Plus, there is less typing and less to read which is a good thing.)

I would certainly not compromise clarity of source code for speed if it produced so little difference.
It just so happens that in this case what I think is easier to read also runs a little faster.
(In the timing above, the increase is 0.31% overall, and is not even worth considering.)

As to whether or not this is important in a Control collection on a Form seems a mute point.
The control count can’t get to 64K+.

Perhaps someone would like to demonstrate a worthwhile speed improvement, which would require a particular method of accessing controls on a Form or Report.

Regards,
Chris.
 
Last edited:
Thanks Pat and I’ll give it a shot.

Could be difficult to time since referring to one control may be below the 1 millisecond resolution I have available to me.

Worth the effort and I’ll give it my best shot. (Could take a while to build a reasonable test case.)

Regards,
Chris.
 
Perhaps you can throw:
Forms("YourFormName")("YourControlName")
int the mix, while you're at it.
 
Actually Pat there is a little more to say on this subject before I get started trying to produce a test case.

When you say “a more valid comparison” there may be no more valid comparison than that which is already posted.

In this thread Milo posted a speed method that seems to be invalid under DAO.

The current thread was not started about DAO but about Controls. But the similarity and timing are remarkable and that is why I prefaced my remarks as “For DAO recordsets... “

However, I will still try to time a control collection.

Why I think it will be difficult to arrive and any concrete answer is because the collection will be restricted in size. I’m not a fond believer of wrapping test cases in a For Next loop as the first pass might have to bring the data to memory and subsequent iterations may not be running “in the real world” with the same overhead.

But it is still worth a shot.

If you have any timing information or the ways to test it, it would be much appreciated.

Regards,
Chris.
 
G’day dcx693

Thanks for the alternative.

Forms("YourFormName")("YourControlName")

Will be included if I can figure a valid way to time it.

If anyone has a valid method, or another reference method, I would like to hear it so it can be included in the testing.

Regards,
Chris.
 
Thanks Pat.

One of my concerns here it that once a point is stated then some readers want others to do all the work. It is not easy to time code, as you will most surly know, but I think that sometimes some people require us to do all the work and somehow provide a concrete solution.

In this case I think it will be difficult to prove.

For example, I’m currently trying to write a non-looping 400-iteration test case to try to prevent ambiguity between first pass and subsequent passes. I don’t want it said that the test case is false, particularly by someone that has not taken the time to run the test for themselves.

As you will know, it is a simple fact that timing needs to be timed.

PS
And may I add it is going to take a while. (A few days.)

Regards,
Chris.
 
Last edited:
Code:
Option Explicit
Option Compare Text


Private Sub cmdGo_Click()
    Dim lngStart     As Long
    Dim lngLoopCount As Long
    
    [color=green]'  Looping time results.
    '  850MHz PIII
    '
    '  Text box named txtTestText
    '  bound to field TestText
    '  100,000 loops
    '  times in milliseconds[/color]
    
    lngStart = timeGetTime()
    For lngLoopCount = 1 To 100000
        Me.txtTestText = "ABC_"
    Next lngLoopCount
    Debug.Print timeGetTime() - lngStart  [color=green]'  3425[/color]

    lngStart = timeGetTime()
    For lngLoopCount = 1 To 100000
        Me!txtTestText = "ABC_"
    Next lngLoopCount
    Debug.Print timeGetTime() - lngStart  [color=green]'  3986[/color]

    lngStart = timeGetTime()
    For lngLoopCount = 1 To 100000
        txtTestText = "ABC_"
    Next lngLoopCount
    Debug.Print timeGetTime() - lngStart  [color=green]'  3425[/color]

    lngStart = timeGetTime()
    For lngLoopCount = 1 To 100000
        Forms!Form1!txtTestText = "ABC_"
    Next lngLoopCount
    Debug.Print timeGetTime() - lngStart  [color=green]'  4957[/color]
    
    lngStart = timeGetTime()
    For lngLoopCount = 1 To 100000
        Forms("Form1")("txtTestText") = "ABC_"
    Next lngLoopCount
    Debug.Print timeGetTime() - lngStart  [color=green]'  4917[/color]
   
    lngStart = timeGetTime()
    For lngLoopCount = 1 To 100000
        Me("txtTestText") = "ABC_"
    Next lngLoopCount
    Debug.Print timeGetTime() - lngStart  [color=green]'  3986[/color]
   
    MsgBox "Done"

End Sub
 
So, to summarize, with the last column indicating how much longer that particular reference style took over the quickest reference style:
Code:
Reference	                         Time	
Me.txtTestText	                         3425	0%
Me!txtTestText	                         3986	16%
txtTestText	                         3425	0%
Forms!Form1!txtTestText                 4957	45%
Forms("Form1")("txtTestText")         	4917	44%
Me("txtTestText")	                3986	16%
Interesting. It's what I would've expected based on what I'd read, but as ChrisO did point out, it's hard to get accurate timing since timing needs to be timed.

Besides, the differences in time all seem rather small. Each loop was executed 100,000 times with the biggest difference being between 3.425 seconds and 4.957 seconds.
 
Last edited:
G’day dcx693

If we can take those timing numbers as correct then your last point is perhaps the important one, for 500 controls on a Form the max. difference would amount to 7.66 milliseconds.

I would still like to make up a Form with 500 different text boxes and write code to go through them without looping. (Which of course means 500 lines of code per each of 6 methods.)

Won’t be able to do much today, visiting relatives, but might have something for tomorrow.

Any other methods to reference controls on a form you might like timed?

Regards,
Chris.
 
ChrisO, thanks again for taking the time to do this. Good job.

I always did wonder if there was any speed difference between:
Me("txtTestText")
Me.Controls("txtTestText")
 
I need to leave shortly to see the rels. but you can have a play with this as it stands.

It’s a bit of an eye opener if you create a command button on one of the Forms and tie it to the update routine.

Timing is not what it seems. :eek:

Regards,
Chris.
 

Attachments

No problems here Pat.

I think you have hit the nail on the head when you refer to tight looping.

To me it makes no sense to have a command button initiate short high-speed single pass code. The processor has done billions of cycles while just waiting for the user to push the button then, all of a sudden, the user wants an instant response. Hey, if they want the code to finish earlier they should have pushed the button sooner. Taking two seconds to push the button and wanting the result 5 microseconds sooner doesn’t seem quite right to me. In this case I prefer easily read source code. The . usually has the advantage of IntelliSense, if that is what it is called, and for me that is sufficient reason to use it in these circumstances.

But when we get into a multi-pass tight loop, things start to change. In this case I prefer tight fast code and readability can go out the window. Therefore, as you say, it helps to know which is the fastest way to do things because then we have a choice.

But to know which is fastest it must be timed and it must be timed in a realistic manner.

As I said previously I’m not a great fan of extrapolating a single pass to the many in a loop nor to interpolate loop time back to the single pass. Too many variables arise and one did during testing.

In the version 1 demo I attached, don’t know if you downloaded it, the time to initially update 400 controls was about 420 milliseconds. Not too bad considering there aren’t that many Forms with four hundred text boxes.

But if you take any one of the 6 Forms and create a command button that calls the update routine, it takes about 7,500 to 10,000 milliseconds to run the update and the timing is all over the shop. This represents a 20:1 timing decay not the trivial 5% in the looping tests.

Why? I don’t hear you ask! And I’m glad I don’t hear you ask because I have absolutely no answer at this stage.

It still needs more testing and the more people to test it the better.

Regards,
Chris.
 
Last edited:
G’day all.

Looks like the timing of control update is far more dependent, not on the method of update, but whether or not the control in visible.

Not the outcome I expected. :eek: :D

New demo attached.

Regards,
Chris.
 

Attachments

G'day all.

This one removes the screen flicker by not using the Form Visible property but turning off screen Echo during the update.

Version 3 attached.

Regards,
Chris.
 

Attachments

Last edited:

Users who are viewing this thread

Back
Top Bottom