I’ve been converting some C# code into VB (because I think better in VB than I do in C#), and the conversion reminded me of another small feature of VB that people tend to forget about. Everyone who’s used Access or VB probably is familiar with the ! operator. Most of the time, you probably used it with DAO/ADO, something like: (Forgive me if the methods are wrong, it’s been a while since I wrote any non-ADO.NET code.)
rs!CustomerName = "John Smith"
rs!Address = "10 Main Street; Seattle, WA"
rs!Phone = "(206) 555-1212"
You probably used the ! operator because you saw someone else using it, and it was a lot easier than writing
rs.Fields("CustomerName") = "John Smith". But you probably never thought about what, exactly, the ! operator was doing. Sadly, the operator has fallen somewhat into disuse because of the advent of strongly-typed datasets in ADO.NET. But it’s still quite handy!
The technical name for the ! operator is the “dictionary lookup operator.” A dictionary is any collection type that is indexed by a key rather than a number, just like the way that the entries in an English dictionary are indexed by the word you want the definition of. The most common example of a dictionary type is the
System.Collections.Hashtable, which allows you to add (key, value) pairs into the hashtable and then retrieve values using the keys. For example, the following code adds three entries to a hashtable, and looks one of them up using the key “Pork”.
Dim Table As Hashtable = New Hashtable Table("Orange") = "A fruit" Table("Broccoli") = "A vegetable" Table("Pork") = "A meat" Console.WriteLine(Table("Pork"))
The ! operator can be used to look up values from any dictionary type that indexes its values using strings. The identifier after the ! is used as the key in the lookup operation. So the above code could instead have been written:
Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
The second example is completely equivalent to the first, but just looks a lot nicer, at least to my eyes. I find that there are a lot of places where ! can be used, especially when it comes to XML and the web, where there are just tons of collections that are indexed by string. One unfortunate limitation is that the thing following the ! still has to be a valid identifier, so if the string you want to use as a key has some invalid identifier character in it, you can’t use the ! operator. (You can’t, for example, say
Table!AB$CD = 5 because $ isn’t legal in identifiers.) In VB6 and before, you could use brackets to escape invalid identifiers (i.e.
Table![AB$CD]), but when we started using brackets to escape keywords, we lost the ability to do that. In most cases, however, this isn’t too much of a limitation.
To get really technical,
x!y works if
x has a default property that takes a
Object as a parameter. In that case,
x!y is changed into
x.DefaultProperty("y"). An interesting side note is that there is a special rule in the lexical grammar of the language to make this all work. The ! character is also used as a type character in the language, and type characters are eaten before operators. So without a special rule,
x!y would be scanned as
x! y instead of
x ! y. Fortunately, since there is no place in the language where two identifiers in a row are valid, we just introduced the rule that if the next character after the ! is the start of an identifier, we consider the ! to be an operator and not a type character.