October 5th, 2007
You probably know that Generics, introduced to VB.NET in the .NET Framework 2.0, provide type safe Lists, Dictionaries, Stacks, Queues and other objects. But, did you know that you can use the same technique to build your own type safe functions? In this article, we’ll look at some of the basics of doing this.
First, let’s look at why generics are important.
Prior to generics we had to base any general purpose routines either around a particular type or use System.Object. This meant that we couldn’t make a routine as general purpose as we might want or we had to use performance impacting boxing to place a value type, such as an integer, into a reference type. Plus we had to use type conversions in many places or, worse, not use Option Strict so that we could do implicit conversions.
With generics, we can work with any type but without incurring performance penalties associated with boxing/unboxing variables or doing any casting. More importantly, we’re insuring type safety and thus avoiding troublesome runtime errors. Using them also makes it easier to build single functions that can work with several different data types.
To begin with, let’s look at how we can define generic type parameters in our own functions. Here’s a simple example that accepts a paramarray of values of a specified type and places then into a generic List of the specified type:
Private Function BuildList(Of T)(ByVal ParamArray values() As T) As List(Of T) Dim NewList As New List(Of T) NewList.AddRange(values) Return NewList End Function
Notice that when the function is defined we specify a generic type first, (Of T), and then our parameters, followed by our return value. Here are some examples of calling this function:
' ' Dim StringList As List(Of String) = BuildList(Of String)("test1", "Hello!", "Bye!") ' ' Dim IntList As List(Of Integer) = BuildList(Of Integer)(1, 87, 48, 28, 24) ' '
As you can see we’re calling the same function but using different data types.
You can also specify multiple types and you’re not limited to just using ‘T’ as the name, as we see in this example that merges two lists of the same size into a dictionary object:
Private Function MergeLists(Of TKey, TValue)(ByVal Keys As List(Of TKey), ByVal Values As List(Of TValue)) As Dictionary(Of TKey, TValue) Dim MergedDictionary As New Dictionary(Of TKey, TValue) If Keys.Count = Values.Count Then Dim Counter As Integer For Each Item As TValue In Values MergedDictionary.Add(Keys.Item(Counter), Item) Counter += 1 Next End If Return MergedDictionary End Function
Calling this function would look like these examples:
' Dim MyItems As Dictionary(Of Integer, String) = MergeLists(Of Integer, String)(IntList, StringList) ' ' Dim MyInventoryResults As Dictionary(Of Integer, InventoryItem) _ = MergeLists(Of Integer, InventoryItem)(KeyList, MyInventoryItems) ' '
Also, we can have specific types in our paramaters while returning a generic type. For example, this function accepts a DataTable and Integer and returns a List object of the specified type with data from the specified column index.
Public Function ColumnToList(Of T)(ByVal MyTable As DataTable, ByVal columnIndex As Integer) As List(Of T) Dim ReturnList As New List(Of T) For Each RowValue As DataRow In MyTable.Rows ReturnList.Add(DirectCast(RowValue(columnIndex), T)) Next Return ReturnList End Function
Any time when you’re coding and you think, “Well, I’ll have to have a separate routine for this data type, and this one, and this one, and this one too”, take the time to consider if using generics will work for you in that case. Often you’ll find that it will.
As always, if you have any questions or ideas on this topic, feel free to leave me a comment.
Entry Filed under: VB.NET Tutorials
Rate This Article: