2003.12.08 08:15 AM

Say "No" to the VB "!" Operator

I hate the "!" operator, also known as the bang or pling. If there was ever a VB language construct that deserved to die, this is it.

I still remember the first time I saw it, in an Access 2.0 VBA help file example. I remember thinking, "What the hell is that and when am I supposed to use it?". As described in the help, one might have concluded that it was the only way to access fields in a DAO recordset or controls on a form. Not surprisingly, its purpose and value remain as unclear now as then. Unfortunately, this lack of clarity has failed to stop countless VB and VBA coders from using it.

Last July, Paul Vick kindly explained that the "!" operator, known in learned circles as the dictionary lookup operator, is shorthand for referencing items in string-keyed dictionaries (think VB collection) having default index properties. He also pointed out that it survived into VB.NET. Here's the official explanation. That's really unfortunate.

Basically, the "!" operator allows you to pretend in code that items in a runtime-static collection are pseudo-properties of the collection object itself. Given this collection in VB or VBA:

Dim c as Collection
Set c = New Collection
c.Add "here's an object", "key"
c.Add "here's another object", "another key"

Or this one in VB.NET:

Dim c as Collection
c = New Collection()
c.Add("here's an object", "key")
c.Add("here's another object", "another key")

You can reference the items in the collection using "!" like this in VB or VBA:

MsgBox c!key
MsgBox c![another key]

Or like this in VB.NET:

Console.WriteLine(c!key)
Console.WriteLine(c![another key])

Sans the "!" operator, here's the normal way to do this in VB or VBA:

MsgBox c("key")
MsgBox c("another key")

Or like this in VB.NET (which is what the compiler turns the "!" into anyway):

Console.WriteLine(c("key"))
Console.WriteLine(c("another key"))

Note that this is just shorthand for the fully qualified syntax, which also works without a default index property, in VB or VBA:

MsgBox c.item("key")
MsgBox c.item("another key")

Or in VB.NET:

Console.WriteLine(c.item("key"))
Console.WriteLine(c.item("another key"))

Had we used an actual dictionary object in .NET, such as a Hashtable, the Add() method would not be necessary, which means the "!" operator could also be used on the left-hand side of the assignment.

So what exactly is the point of using the "!" operator? Mr. Vick thinks it's "handy" and, in some cases "looks a lot nicer". I suppose there's no arguing with that. Anything to save a keystroke or two.

Unfortunately, you also get a pain in the ass when at design-time you need to find every reference to a collection item's string key and change it, because you can't just do a search for the quoted text. It requires multiple searches, or a complex regular expression. In fact, when renaming or removing a static collection item (think rename or remove a table column, or a form control), how many of you would even think to search for literal, non-quoted, !-prefixed references to the item's key? Now imagine a collection item with a key of "for" or "then". (This scenario, in a piece of code I recently inherited, is what prompted this writing.)

Mr. Vick goes on to explain that use of the "!" operator in VB.NET requires your collection keys contain only valid identifier characters (e.g., no "$"), because "!" is also a type character, so the VB.NET compiler uses a hack rule to distinguish its dual use. Yuck. If this isn't indicative of a language abomination, I'm not sure what is. In light of the otherwise great work the language team did on VB.NET, I can only conclude that this turkey was allowed to tag along for compatibility reasons. Surely someone on the team stepped up and said "no"?

Perhaps, though, what I find most disturbing about this syntax, is that it gives the impression of being compile-time checked, when in fact, as with any arbitrary runtime collection evaluation, it is not. This seems at odds with a language (or, more precisely, a language team) that goes to so much trouble to support the lowest common VB coder denominator.

So, please join me in foreswearing the "!" operator. Forever. If you run into a "!" operator somewhere, please take a moment and replace it. And, if you ever feel compelled to address a collection item like a static property, please take a deep breath, relax, and resist the urge to do it with a "!". Wrap it with a class and add a real property instead.

Perhaps in time, if we all pitch in, we'll be able to cruise the universe of VB code safe from the bang and pling.


Comments

Amusing. thanx for the data.

fuzzyami | 2004.11.09 12:56 AM

Thank you for this very useful information. This point helps us in migrating code from VB6 to VB.NET better.

sultan | 2004.12.14 11:42 PM

Ever seen a := sign in a method call? I assume it's a construct from an older version of VB but I can find no documentation on what it means or is used for.

nick | 2005.08.18 10:44 AM

nick,

That's used to pass values to parameters by name. For instance, given this routine:

Sub MyRoutine(ByVal s As String, ByVal l As Long, Optional ByVal i As Integer = 0, Optional ByVal yn As Boolean = False)

You could call it as:

MyRoutine(l:=5, s:="Hey!", yn:=True)

Passing parameters by name means you don't have to worry about the signature order of parameters and it allows you to easily skip optional parameters.

ewbi.develops | 2005.08.18 01:30 PM

This is good stuff. However, I was wondering if you could shed more light on the usage of the Dictionary Lookup Operator (!) specifically for Visual Basic 6. I have an MS Access student database with the following fields:
> StudentNumber
> StudentName
> StudentAge
> StudentClass
How will I use the ! operator in this database?

Taona Ralph | 2008.09.17 02:18 AM

Taona, I'd recommend you don't.

ewbi.develops | 2008.10.21 07:10 PM

I have resently revisited this and I now have to disagree. Using the ! operator in conjunction with a With block can really cut down on the cruft.

Jonathan Allen | 2009.12.08 03:57 PM

Hi Jonathan, I'd really be interested in seeing an example. Not sure it will change my mind, but it might help others who stumble onto this old post make up theirs. Don't worry too much about the formatting, as this old Typepad blog will eat any extra indents anyway.

ewbi.develops | 2009.12.08 07:26 PM

Did "!" died?

juan | 2010.08.11 05:40 AM


TrackBack

TrackBack URL:  http://www.typepad.com/services/trackback/6a00d8341c7bd453ef00d83467b9ae69e2

Listed below are links to weblogs that reference Say "No" to the VB "!" Operator: