Section 25.4. Type Constraints


25.4. Type Constraints

In this section, we present a generic Maximum method that determines and returns the largest of its three arguments (all of the same type). The generic method in this example uses the type parameter to declare both the method's return type and its parameters. Normally, when comparing values to determine which one is greater, you would use the > operator. However, this operator is not overloaded for use with every type that is built into the FCL or that might be defined by extending the FCL types. Generic code is restricted to performing operations that are guaranteed to work for every possible type. Thus, an expression like variable1 < variable2 is not allowed unless the compiler can ensure that the operator < is provided for every type that will ever be used in the generic code. Similarly, you cannot call a method on a generic-type variable unless the compiler can ensure that all types that will ever be used in the generic code support that method.

IComparable(Of T) Interface

It is possible to compare two objects of the same type if that type implements the generic interface IComparable(Of T) from namespace System. A benefit of implementing this interface is that IComparable(Of T) objects can be used with the sorting and searching methods of classes in the System.Collections.Generic namespacewe discuss these methods in Chapter 26, Collections. The structures in the FCL that correspond to the primitive types (such as Int32 for primitive type Integer) all implement this interface. Types that implement IComparable(Of T) must declare a CompareTo method for comparing objects. For example, if we have two Integers, integer1 and integer2, they can be compared with the expression:

 integer1.CompareTo(integer2) 


Method CompareTo must return 0 if the objects are equal, a negative integer if integer1 is less than integer2 or a positive integer if integer1 is greater than integer2. It is the responsibility of the programmer who declares a type that implements IComparable(Of T) to declare method CompareTo such that it compares the contents of two objects of that type and returns the appropriate result.

Specifying Type Constraints

Even though IComparable objects can be compared, they cannot be used with generic code by default, because not all types implement interface IComparable(Of T). We can, however, restrict the types that can be used with a generic method or class to ensure that they meet certain requirements. This featureknown as a type constraintlimits the type arguments that can be supplied to a particular type parameter. Figure 25.4 declares method Maximum (lines 1631) with a type constraint that requires each of the method's arguments to be of type IComparable(Of T). This restriction is important because not all objects can be compared. However, all IComparable(Of T) objects are guaranteed to have a CompareTo method that can be used in method Maximum to determine the largest of its three arguments.

Figure 25.4. Generic method Maximum with a type constraint on its type parameter

  1  ' Fig 25.4: MaximumTest.vb  2  ' Generic method maximum returns the largest of three objects.  3  Module MaximumTest  4     Sub Main()  5        Console.WriteLine( "Maximum of {0}, {1} and {2} is {3}" & _  6           vbCrLf, 3, 4, 5, Maximum(3, 4, 5))  7        Console.WriteLine("Maximum of {0}, {1} and {2} is {3}" & _  8           vbCrLf, 6.6, 8.8, 7.7, Maximum(6.6, 8.8, 7.7))  9        Console.WriteLine("Maximum of {0}, {1} and {2} is {3}" & _ 10           vbCrLf, "pear", "apple", "orange", _ 11           Maximum("pear", "apple", "orange")) 12     End Sub' Main 13 14     ' generic function determines the 15     ' largest of the IComparable objects 16     Public Function Maximum(Of T As IComparable(Of T)) _ 17        (ByVal x  As T, ByVal y  As T, ByVal z  As T) As T 18        Dim max  As T = x ' assume x is initially the largest 19 20        ' compare y with max 21        If y.CompareTo(max) > 0 Then 22           max = y ' y is the largest so far 23        End If 24 25        ' compare z with max 26        If z.CompareTo(max) > 0 Then 27            max = z ' z is the largest 28        End If 29 30        Return max ' return largest object 31     End Function' Maximum 32   End Module' MaximumTest  

 Maximum of 3, 4 and 5 is 5 Maximum of 6.6, 8.8 and 7.7 is 8.8 Maximum of pear, apple and orange is pear 



Generic method Maximum uses type parameter T as the return type of the method (line 17), as the type of method parameters x,y and z (line 17), and as the type of local variable max (line 18). Generic method Maximum specifies the type constraint for type parameter T in its type parameter list in line 16. In this case, the type parameter list (Of T As IComparable(Of T)) indicates that this method requires the type arguments to implement interface IComparable(Of T). If no type constraint is specified, the default type constraint is Object.

Visual Basic provides several kinds of type constraints. A class constraint indicates that the type argument must be an object of a specific base class or one of its subclasses. An interface constraint indicates that the type argument's class must implement a specific interface. The type constraint in line 16 is an example of an interface constraint, because IComparable( OfT) IComparable(Of T) is an interface. You can specify that the type argument must be a reference type or a value type by using the reference type constraint (Class) or the value type constraint (Structure), respectively. Finally, you can specify a New constraint to indicate that the generic code can use operator New to create new objects of the type represented by the type parameter. If a type parameter is specified with a New constraint, the type argument's class must be a concrete class. Also, the class must provide a Public parameterless or default constructor to ensure that objects of the class can be created without passing constructor arguments; otherwise, a compilation error occurs.

It is possible to apply multiple constraints to a type parameter. To do so, simply provide a comma-separated list of constraints in the type parameter list. If you have a class constraint, reference type constraint or value type constraint, it must be listed firstonly one of these types of constraints can be used for each type parameter. Interface constraints (if any) are listed next. The New constraint is listed last (if there is one).

Analyzing the Code

Method Maximum assumes that its first argument (x) is the largest and assigns it to local variable max (line 18). Next, lines 2123 determine whether y is greater than max. The condition invokes y's CompareTo method to compare y to max. If y is greater than max, then y is assigned to variable max (line 22). Similarly, lines 2628 determine whether z is greater than max. If so, line 27 assigns z to max. Then line 30 returns max to the caller.

In Main (lines 412), line 6 calls Maximum with the integers 3, 4 and5. Genericmethod Maximum is a match for this call, but its arguments must implement interface IComparable(Of T) to ensure that they can be compared. Type Integer is a synonym for Structure Int32, which implements interface IComparable(Of Integer). Thus, Integers (and other primitive types) are valid arguments to method Maximum.

Line 8 passes three Double arguments to Maximum. Again, this is allowed because primitive type Double is a synonym for the FCL's Double Structure, which implements IComparable(Of Double). Line 11 passes Maximum tHRee Strings, which are also IComparable(Of String) objects. Note that we intentionally placed the largest value in a different position in each method call (lines 6, 8 and 11) to show that the generic method always finds the maximum value, regardless of its position in the argument list and regardless of the inferred type argument.




Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net