Deitel & Associates, Inc. Logo

Back to www.deitel.com
digg.png delicious.png blinkit.png furl.png
Visual Basic 2005
How to Program, 3/e

ISBN:
0-13-186900-0
© 2005
pages: ~1500

Pre-order!
Amazon logo

This is the third in a series of three articles that shows how to declare and use generic methods in the C# programming language. In Part 1, we introduced the concept of generics. In Part 2, we presented an example using overloaded methods to motivate the need for generic methods. In this article we reimplement the overloaded methods from the example in Part 2 using a single generic method. These articles are intended for students who are already familiar with Visual Basic and for Visual Basic developers.
Download the code examples for this tutorial here.

[Note: This three-part tutorial is an excerpt (Sections 25.1-3) of Chapter 25, Generics, from our forthcoming textbook Visual Basic 2005 How to Program, 3/e. This tutorial may refer to other chapters or sections of the book that are not included here. Permission Information: Deitel, Harvey M. and Paul J., Visual Basic 2005 How to Program, ©2005. Electronically reproduced by permission of Pearson Education, Inc., Upper Saddle River, New Jersey.]

25.3 Generic Method Implementation

The overloaded methods of Fig. 25.1 can be more compactly and conveniently coded using a single generic method. You can write a single generic method declaration that can be called at different times with arguments of different types. Based on the types of the arguments passed to the generic method, the compiler handles each method call appropriately.

Figure 25.3 reimplements the application of Fig. 25.1 using a single generic PrintArray method (lines 19–25). Note that the PrintArray method calls in lines 11, 13 and 15 are identical to those in Fig. 25.1, the outputs of the two applications are identical and the code in Fig. 25.3 is 18 lines shorter than the code in Fig. 25.1. As illustrated in Fig. 25.3, generics enable us to create and test our code once, then reuse the code for many different types of data. This demonstrates the expressive power of generics.

Fig. 25.3 | Printing array elements using generic method PrintArray.
1    ' Fig. 25.3: GenericMethod.vb
2    ' Using overloaded methods to print arrays of different types.
3    Module GenericMethod
4      Sub Main()
5          ' create arrays of integer, double and char
6         Dim integerArray As Integer() = {1, 2, 3, 4, 5, 6}
7         Dim doubleArray As Double() = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7}
8         Dim charArray As Char() = {"H"c, "E"c, "L"c, "L"c, "O"c}
9   
10         Console.WriteLine("Array integerArray contains:")
11         PrintArray(integerArray) ' pass an integer array argument
12         Console.WriteLine("Array doubleArray contains:")
13         PrintArray(doubleArray) ' pass a double array argument
14         Console.WriteLine("Array charArray contains:")
15         PrintArray(charArray) ' pass a char array argument
16      End Sub ' Main
17   
18       ' output array of all types
19      Public Sub PrintArray(Of E)(ByVal inputArray() As E)
20         For Each element As E In inputArray
21            Console.Write(element.ToString() & " ")
22         Next element
23   
24         Console.WriteLine(vbCrLf)
25      End Sub ' PrintArray
26    End Module ' GenericMethod

Array integerArray contains:
1 2 3 4 5 6

Array doubleArray contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7

Array charArray contains:
H E L L O

Line 19 begins method PrintArray's declaration. All generic method declarations have a type parameter list delimited by parentheses(Of E) in this examplethat follows the method's name. Each type parameter list begins with the keyword Of and contains one or more type parameters separated by commas. A type parameter is an identifier that is used in place of actual type names. The type parameters can be used to declare the return type, the parameter types and the local variable types in a generic method declaration; the type parameters act as placeholders for the types of the arguments passed to the generic method. A generic method's body is declared like that of any other method. Note that the type parameter names throughout the method declaration must match those declared in the type parameter list. For example, line 20 declares element in the For Each statement as type E, which matches the type parameter (E) declared in line 19. Also, a type parameter can be declared only once in the type parameter list but can appear more than once in the method's parameter list. Type parameter names need not be unique among different generic methods.

Common Programming Error 25.1

If you forget to include the type parameter list when declaring a generic method, the compiler will not recognize the type parameter names when they are encountered in the method. This results in compilation errors.

Method PrintArray's type parameter list (line 19) declares type parameter E as the placeholder for the array element type that PrintArray will output. Note that E appears in the method's parameter list as the array element type (line 19). The For Each statement header (line 20) also uses E as the element type. These are the same two locations where the overloaded PrintArray methods of Fig. 25.1 specified Integer, Double or Char as the array element type. The remainder of PrintArray is identical to the version in Fig. 25.1.

Good Programming Practice 25.1

According to msdn.microsoft.com/library/en-us/
dndotnet/html/BestPractices.asp
, it is recommended that type parameters be specified as individual capital letters. Typically, a type parameter that represents the type of an element in an array (or other collection) is named E for "element" or T for "type."

As in Fig. 25.1, the program in Fig. 25.3 begins by declaring and initializing six-element Integer array integerArray (line 6), seven-element Double array doubleArray (line 7) and five-element Char array charArray (line 8). Then each array is output by calling PrintArray (lines 11, 13 and 15)—once with argument integerArray, once with argument doubleArray and once with argument charArray.

When the compiler encounters a method call, such as line 11, it analyzes the set of methods (both non-generic and generic) that might match the method call, looking for a method that matches the call exactly. If there are no exact matches, the compiler picks the best match. If there are no matching methods, or if there is more than one best match, the compiler generates an error. The complete details of method-call resolution can be found in Section 11.8.1 of the Visual Basic Language Specification version 8.0, which can be downloaded from:

www.microsoft.com/downloads/details.aspx?FamilyId=6D50D709-
EAA4-44D7-8AF3-E14280403E6E&displaylang=en

For line 11, the compiler determines that an exact match occurs if the type parameter E in lines 19 and 20 of method PrintArray's declaration is replaced with the type of the elements in the method call's argument integerArray (i.e., Integer). Then the compiler sets up a call to PrintArray with Integer as the type argument for the type parameter E. This is known as the type inferencing process. The same process is repeated for the calls to method PrintArray in lines 13 and 15.

Common Programming Error 25.2

If the compiler cannot find a single non-generic or generic method declaration that is a best match for a method call, or if there are multiple best matches, a compilation error occurs.

You can also use explicit type arguments to indicate the exact type that should be used to call a generic function. For example, line 11 could be written as

PrintArray(Of Integer)(integerArray) ' call Integer version

In the preceding method call, the first set of parentheses contains the explicit type argument Integer that should be used to replace type parameter E in lines 19 and 20 of method PrintArray's declaration.

The compiler also determines whether the operations performed on the method's type parameters can be applied to elements of the type stored in the array argument. The only operation performed on the array elements in this example is to output the String representation of the elements. Line 21 calls ToString on the current array element being processed. Since all objects have a ToString method, the compiler is satisfied that line 21 performs a valid operation for any array element.

By declaring PrintArray as a generic method in Fig. 25.3, we eliminated the need for the overloaded methods of Fig. 25.1, saving 18 lines of code and creating a reusable method that can output the string representations of the elements of any array, not just arrays of Integer, Double or Char elements.

Tutorials in This Series:
Introduction to Generics in Visual Basic
Motivation for Generic Methods
Generic Method Implementation (You are here.)

Tutorial Index