views:

234

answers:

2

While perusing an application that I'm documenting, I've run across some examples of bang notation in accessing object properties/methods, etc. and in other places they use dot notation for what seems like the same purpose.

Is there a difference or preference to using one or the other? Some simple googling only reveals limited information on the subject with some people actually using it in opposite cases. Perhaps there is a coding standards section from MS somewhere that indicates the method of madness?

+1  A: 

This is quite an old and largely debated topic, google for

bang vs dot dao vba

For some interesting writing.

Remou
+9  A: 

The bang operator (!) is shorthand for accessing members of a Collection or other enumerable object, such as the Fields property of an ADODB.Recordset.

For example, you can create a Collection and add a few keyed items to it:

Dim coll As Collection
Set coll = New Collection

coll.Add "First Item", "Item1"
coll.Add "Second Item", "Item2"
coll.Add "Third  Item", "Item3"

You can access an item in this collection by its key in three ways:

  1. coll.Item("Item2")
    This is the most explicit form.

  2. coll("Item2")
    This works because Item is the default method of the Collection class, so you can omit it.

  3. coll!Item2
    This is short-hand for both of the above forms. At run-time, VB6 takes the text after the bang and passes it as a parameter to the Item method.

People seem to make this more complicated than it should be, which is why it's hard to find a straightforward explanation. Usually the complications or "reasons not to use the bang operator" stem from a misunderstanding of how simple it actually is. When someone has a problem with the bang operator, they tend to blame it instead of the real cause of the problem they are having, which is often more subtle.

For example, some people recommend not using the bang operator to access controls on a form. Thus, Me.txtPhone is preferred over Me!txtPhone. The "reason" this is seen as bad is that Me.txtPhone will be checked at compile-time for correctness, but Me!txtPhone won't.

In the first case, if you mistype the code as Me.txtFone and there is no control with that name, your code won't compile. In the second case, if you wrote Me!txtFone, you won't get a compile error. Instead, your code will blow up with a run-time error if it reaches the line of code that used Me!txtFone.

The problem with the argument against the bang operator is that this problem has nothing to do with the bang operator itself. It's behaving exactly the way it's supposed to.

When you add a control to a form, VB automatically adds a property to your form with the same name as the control you added. This property is part of the form's class, so the compiler can check for typos at compile-time if you access controls using the dot (".") operator (and you can access them using the dot operator precisely because VB created a named control property for you).

Since Me!ControlName is actually short-hand for Me.Controls("ControlName")1, it should not be suprising that you don't get any compile-time checks against mistyping the control name.

Put another way, if the bang operator is "bad" and the dot operator is "good", then you might think

Me.Controls("ControlName")

is better than

Me!ControlName

because the first version uses a dot, but in this case, the dot isn't any better at all, since you are still accessing the control name via a parameter. It's only "better" when there is an alternative way to write the code such that you will get compile-time checking. This happens to be the case with controls due to VB creating properties for each control for you, and this is why Me.ControlName is sometimes recommended over Me!ControlName.


  1. I had originally stated that the Controls property was the default property of the Form class, but David pointed out in the comments that Controls isn't the default property of Form. The actual default property returns a collection that includes the contents of Me.Controls, which is why the bang short-hand still works.
Mike Spross
Me.Controls is *not* the default "property" of the form object. The default *collection* for Me in a form or report is a union of the Controls and Fields collections. In as standalone class module, there is no default collection. Otherwise, and excellent answer that recapitulates an answer I posted a short while ago that I'm too lazy to look up!
David-W-Fenton
@David: Sorry about that, I was thinking VB6 when I posted my answer, where the `Form` class doesn't have a `Fields` collection. I'll edit my answer to clarify. But now that you mention it, technically `Controls` isn't the default proeperty of `Form` in VB6 either: there is a hidden property called `_Default` that is listed as the default member of the class. Not sure if it is a union of multiple collections in VB6 or if it simply returns `Controls`. Good catch though. Now you've got me wanting to solve this mystery :-)
Mike Spross
And coll.Item("Item2") isn't always the full story either. In most contexts you really mean coll.Item("Item2").Value, however in some places where an object reference is acceptable the object's default property (.Value) won't be selected. This can lead to hard to find errors, but it is rare. Note that this is not a failing of the ! syntax itself however.
Bob Riemersma
@Bob: I considered adding that as another example where the bang operator is sometimes incorrectly blamed. I've seen a few times where someone suggests using `rs.Fields("ColumnName").Value` because `rs!ColumnName` "doesn't always work", but as you point out, any problems are due to not being explicit about using the `Value` property, in those situations where it does actually make a difference. `rs!ColumnName.Value` would have just as easily solved the problem, so just another case where the blame is misplaced, and the real issue is how and when VB6 evaluates default properties.
Mike Spross
I'm not sure if adding .Value will always work. Starting with A2000, there's been a disconnect between the form/report and the underlying recordsource, and this is reflected in the need to have a control with a controlsource for any field that you refer to in code. That is, if MyField is in the recordsource, but there is no control with it as ControlSource, referring to it in code is unreliable, not because of . or ! or .Value, but because MS has mucked up the relationship between the form/report and its Fields collection.
David-W-Fenton