Visual Basic.NET in Whidbey

In this preview chapter, you’ll learn about two new significant enhancements to Visual Basic.NET in Whidbey. The first of these is Generics. With Generics, you can create strongly typed collections with a single line of code. When doing so, you reap the benefits of improved IntelliSense, as the data types for collection keys and values are known at design time. You can also create operations and algorithms that are both strongly typed, and work over a wide range of data types. Next you’ll learn about The My namespace . The My namespace is a Visual Basic.NET only feature in Whidbey that functions as both a speed dial for the .NET Framework and a provider of new and enhanced features to the Visual Basic.NET language. With My you can be more productive when building applications in Visual Basic.NET than with previous releases of Visual Basic .NET.
Application: Generics
This application illustrates the new Visual Basic .NET support for generics.
New Concepts
Before getting into the implementation of generics, it’s worth spending a minute to analyze why this feature has been added to Visual Basic .NET. Generics come from the need to deal with potentially any type of object in a “generic” way. Even without “generics”, Visual Basic has always provided some mechanisms for dealing with objects, regardless of their type. For example, with Visual Basic 6.0, you can store objects of any type in a Collection class.
Visual Basic 6.0 Collections
Visual Basic 6.0 really lets you just about anything in a Collection. However, the Collection class has a number of limitations. For example, let’s say that you want to store the following Employee class in a Collection:
‘ Visual Basic 6.0 Code
Public SSN As String
Public FirstName As String
Public LastName As String
Public Salary As Currency
Storing this in the collection is relatively straightforward.
‘ Visual Basic 6.0 Code
Dim employees As New Collection

Dim emp As Employee
Set emp = New Employee
emp.SSN = "111-11-1111"
emp.FirstName = "Scott"
emp.LastName = "Swigart"
emp.Salary = 50000

employees.Add emp, emp.SSN
This code first creates an instance of a Collection called employees. An Employee class is then created, and populated with data. Finally, this Employee is added to the Collection, specifying the emp.SSN property as the key. The following code shows how the Employee could then be retrieved from the Collection:
‘ Visual Basic 6.0 Code
Dim emp2 As Employee
Set emp2 = employees("111-11-1111")
Now lets examine the limitations of the Visual Basic 6.0 Collection. First, it’s pretty likely that you want to store only Employee classes in the employees collection. However, there is nothing to prevent anyone from storing any other type of object in the Employees collection. In addition, when you attempt to retrieve an item from the Employees collection, there’s nothing to let you know what type you’re retrieving. For example, the following code will compile just fine:
Dim s As String
s = employees("111-11-1111")
Although it’s obvious to the developer that this can’t work, there’s no way the compiler can catch this. This will instead show up as a runtime error. Collections also limit the ability of IntelliSense. Consider the following code:
employees("111-11-1111").LastName = "SomeoneElse"
This shows that you can directly edit an item while it is in a Collection. However, you won’t have any IntelliSense support when selecting the LastName property. Again, from the perspective of Visual Basic, that Collection could be storing anything.
Two final limitations of the collection class are performance and flexibility. While easy to use, a collection class performs poorly when used as a dynamic array. A collection class is also designed to work like a dictionary, so if you need something more like a Stack or Queue, it’s not a good fit.
Framework Collections
The.NET Framework 1.0/1.1 solved some of the problems with collections by simply offering more types of collections. By importing the System.Collections namespace, your code gained access to such collections as the ArrayList, BitArray, HashTable, Queue, SortedList, and Stack. The usage scenario for these types of collections is shown in the following table:
Table 3-X Collection Classes
Collection Name Use
ArrayList The ArrayList makes it easy to create arrays that grow dynamically.
BitArray The BitArray class is optimized to store an array of Boolean (true/false) values.
HashTable The HashTable is most like the Visual Basic 6 Collection class. This class allows you to look up values using a key. However, the key and the value can be any type.
SortedList A SortedList is similar to a HashTable, except that the keys are always sorted. This means that if you use For…Each to iterate through the collection, you will always retrieve the items in a sorted order.
Queue A Queue is a collection that provides access to its contained objects on a first in, first out basis.
Stack A Stack, provides access to its contained objects on a first in, last out basis.
The .NET Framework 1.0/1.1 did much to solve the flexibility limitations of Visual Basic 6.0, however, these collections are still loosely typed. This means that you can store anything in an ArrayList, even if, for a given application, it only makes sense to store a specific type.
What you really want is a collection where you can specify that every key must be a String and every value must be an Employee. With the .NET Framework 1.0/1.1, you would have been required to create your own class that inherits one of the collection base classes, which isn’t trivial. With the .NET Framework 1.2, this is solved with far less code, using generics.
Code Walkthrough
As the “Generics” application shows, generics provide strict type checking, better IntelliSense functionality, and better performance. In other words, they address pretty much all the issues with collection classes of the past.
Consuming Generic Types
As you will see, when you create an instance of a generic collection, you provide the information needed to make that collection strongly typed. This offers many advantages, including safer and more reliable code as more checks can be done at compile time, better IntelliSense, and better performance. However, it’s worth mentioning that the .NET Framework 1.2 provides generic collections in addition to the existing .NET Framework 1.0/1.1 collection classes. The .NET Framework 1.2 in no way forces you to use generics.
If you do want to use the new generic types, you begin by importing the System.Collections.Generic namespace. This grants access to Dictionary, List, Queue, SortedDictionary, and Stack classes. An example of using the generic Dictionary is shown in the btnConsumeGenerics_Click event:
‘ Visual Basic .NET 8.0 code
Private Sub btnConsumeGenerics_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConsumeGenerics.Click
Dim employees As New Dictionary(Of String, Employee)
Dim emp As Employee
emp = New Employee
emp.SSN = "111-11-1111"
emp.FirstName = "Scott"
emp.LastName = "Swigart"
emp.Salary = 50000

employees.Add(emp.SSN, emp)

Dim emp2 As Employee
emp2 = employees.Item("111-11-1111")

Dim s As String
's = employees.Item("111-11-1111") ' This is now a syntax error

employees.Item("111-11-1111").LastName = "SomeoneElse"
End Sub
If you walk through the code, you will notice a few interesting facts about generics. First, the generic type is instantiated as follows:
Dim employees As New Dictionary(Of String, Employee)
This translates to ‘Create a Dictionary where the keys will be Strings and the values will be Employees”. Any attempt to store anything other than an Employee will result in a compile time error. That’s worth repeating. With generics, if you use the wrong type, it’s a compile time error, not a runtime error. In fact, the following line must be commented out, or the application will not run, as the compiler knows that the Dictionary holds Employee classes, not Strings:
's = employees.Item("111-11-1111") ' This is now a syntax error
In addition, you now have full IntelliSense for the types in your collection. If you examine the following figure, you can see that Visual Studio knows that this Dictionary holds only Employee classes, and the properties of the Employee class are available through IntelliSense:
Figure4-X
IntelliSense for items in a generic collection

As you can see, generics are simple to use, they result in strongly typed code (which reduces the possibility for runtime errors), and they allow IntelliSense to be more functional. Those would be reasons enough to use generics, but they have a number of additional advantages as well; performance, and code reuse.
One of the main reasons for including generics in the Framework is performance. Simply put, they’re faster than the previous collection classes because the compiler optimizes them specifically for the types they store. An example can be seen in the following code which compares the performance of an array, ArrayList, and generic List:
txtOutput.Text = "Performance" & vbCrLf

Const iterations As Integer = 5000000
PerfTime.Start()
Dim myArray(iterations) As Integer
For i As Integer = 0 To iterations - 1
myArray(i) = i
Next
Dim elapsed As Integer = PerfTime.Stop
txtOutput.Text &= "Array time: " & elapsed & vbCrLf
myArray = Nothing
GC.Collect()

PerfTime.Start()
Dim myArrayList As New ArrayList
For i As Integer = 0 To iterations - 1
myArrayList.Add(i)
Next
elapsed = PerfTime.Stop
txtOutput.Text &= "ArrayList time: " & elapsed & vbCrLf
myArrayList = Nothing
GC.Collect()

PerfTime.Start()
Dim myList As New List(Of Integer)
For i As Integer = 0 To iterations - 1
myList.Add(i)
Next
elapsed = PerfTime.Stop
txtOutput.Text &= "List time: " & elapsed & vbCrLf
myList = Nothing
GC.Collect()
This code stores 5 million values into a fixed sized array. The values are also stored in an ArrayList which grows automatically, and a generic List which also grows as needed. The performance numbers tell an interesting story:
Array time: 344
ArrayList time: 4656
List time: 797
Nothing is faster than an array that stores a specific type, and never needs to resize. However, for a collection class that grows dynamically, to be ½ the speed of a static array is pretty good. And look at the ArrayList. Not good. It’s less than 1/10th the speed of the static array. The problem is that the ArrayList is designed to store objects. Integers are not objects, they’re value types. Before they can be stored into the ArrayList, they have to go through a process called “boxing”, which converts the Integer to an Object. Boxing is expensive, and if you are storing value types (Integer, DateTime, Boolean, your own structures, etc.) then you will notice a significant performance improvement using generic collections over the Object based collections.
For more information on boxing and unboxing, see “Boxing Conversions”, and “Unboxing Conversions” in the MSDN library.
Creating Generic Types and Methods
You are not limited to simply consuming generic types with Visual Basic .NET. You have the ability to also create your own generic types and methods.
Generic Methods
You may want to create a generic method if there is some common algorithm you wish to perform that is independent of any type. For example, a typical bubble sort walks through all the items in an array, comparing one item with the next, and swapping the values as needed to sort the array.
If you know in advance that you’re only going to be sorting integers, then you could simply hard-code the Swap method for Integer types. However, if you wanted to be able to sort any type, then you could code a generic Swap as follows:
Private Sub Swap(Of ItemType) _
(ByRef v1 As ItemType, ByRef v2 As ItemType)

Dim temp As ItemType
temp = v1
v1 = v2
v2 = temp
End Sub
Notice the “Of ItemType”. When the Swap method is called, in addition to the standard arguments, a data type must also be passed. This data type will be substituted for every instance of ItemType. The following is an example of a call to Swap:
Swap(Of Integer)(v1, v2)
This tells the Swap method that it will be swapping Integer types. If you refer to the original listing of Swap, this will cause every instance of ItemType to be replaced with Integer by the JIT compiler. The Swap method is essentially rewritten by the JIT to the following:
Private Sub Swap(ByRef v1 As Integer, ByRef v2 As Integer)
Dim temp As Integer
temp = v1
v1 = v2
v2 = temp
End Sub
This is the code that’s actually executed. The JIT generates a version of the method to handle Integer types. However, if you later wanted to sort String types, you could have another call to Swap as follows:
Swap(Of String)(v1, v2)
When this method executed, the JIT will write another version of Swap, this one specialized for String types;
Private Sub Swap(ByRef v1 As String, ByRef v2 As String)
Dim temp As String
temp = v1
v1 = v2
v2 = temp
End Sub
A full example of a bubble sort that uses Swap is as follows:
Private Sub btnSortIntegers_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSortIntegers.Click
Dim ints(9) As Integer
Dim r As New Random
For i As Integer = 0 To 9
ints(i) = r.Next(1, 100)
Next

' Bubble sort
For j As Integer = 0 To 9
For k As Integer = 9 To 1 Step -1
If ints(k) < ints(k - 1) Then
Swap(Of Integer)(ints(k), ints(k - 1))
End If
Next
Next

txtOutput.Text = "Sort Integers" & vbCrLf
For i As Integer = 0 To 9
txtOutput.Text &= ints(i) & vbCrLf
Next
End Sub

Generic Types
As a final point, you can create entire generic classes. In this case the “Of ItemType” is use with the class declaration as follows:
Public Class SomeClass(Of ItemType)

Private internalVar as ItemType
Public Function SomeMethod(ByVal value As ItemType) As ItemType
End Function

End Class
The same rules apply to classes as methods. The JIT compiler will simply replace every instance of ItemType with a specific type when the class is instantiated.
Constraints
Generics also support a feature known as constraints. This lets you insure that when specify types, they implement certain minimum functionality. For example if you are implementing a generic sort algorithm, you may wish to insure that the type that your sorting implements IComparible. You can accomplish this with a constraint:
Public Class SomeClass(Of ItemType As IComparible)

Public Function SomeMethod(ByVal value As ItemType) As ItemType
End Function

End Class

Conclusion
Generics offer a number of advantages over Object based collection classes. First, generic classes are strongly typed, which allows many errors to be caught at compile time, rather than runtime. The strong typing also lets IntelliSense provide more information. Generics also allow you to reuse your code, creating generic algorithms that work over a variety of types. Finally, generic collections are just faster than Object based collections, especially when dealing with value types.