Appendix M

Generics

This appendix summarizes generic classes, extensions, and methods. The final section in this appendix describes items that you cannot make generic.

GENERIC CLASSES

The syntax for declaring a generic class is as follows:

[attribute_list] [Partial] [accessibility] [Shadows] [inheritance] _
Class name [(Of type_list)]
    [Inherits parent_class]
    [Implements interface]
    statements
End Class

All of these parts of the declaration are the same as those used by a normal (non-generic) class. See Chapter 25, “Classes and Structures,” and Appendix K for information about non-generic classes.

The key to a generic class is the (Of type_list) clause. Here, type_list is a list of data types separated by commas that form the generic’s parameter types. Each type can be optionally followed by the keyword As and a list of constraints that the corresponding type must satisfy. The constraint list can contain any number of interfaces and, at most, one class. It can also contain the New keyword to indicate that the corresponding type must provide a parameterless constructor. If a constraint list contains more than one item, the list must be surrounded by braces.

The following code defines the generic MyGeneric class. It takes three type parameters. The first is named Type1 within the generic’s code and has no constraints. The second type, named Type2, must satisfy the IComparable interface. The third parameter, named Type3, must provide a parameterless constructor, must satisfy the IDisposable interface, and must inherit directly or indirectly from the Person class.

Public Class MyGeneric(Of _
 Type1, 
 Type2 As IComparable, 
 Type3 As {New, IDisposable, Person})

GENERIC EXTENSIONS

Because of their somewhat idiosyncratic nature, extension methods add an extra level of complexity to generics.

Normally, a generic class declaration includes the types on which it depends and the code within the class can use those types. For example, consider the Schedule class shown in the following code, which represents a schedule of tasks:

' Represents a schedule of Tasks.
Public Class Schedule(Of Task)
    Public Sub AddTask(ByVal new_task As Task)
        ...
    End Sub
    ...
End Class

The type list for the Schedule class includes a type named Task and the class’s code can use the type Task. In this example, the AddTask subroutine takes a parameter of this type.

Now suppose you want to add an extension method named Prioritize to the generic Schedule class. The first parameter in the extension method’s declaration indicates the class that the method extends. In this case, that should be Schedule(Of Task), but the extension method itself must also be generic, so it must use a type list just as any other generic method does.

The result is the following declaration.

Imports System.Runtime.CompilerServices
 
Public Module ScheduleExtensions
    ' Prioritizes the schedule.
    <Extension()> 
    Sub Prioritize(Of T)(sched As Schedule(Of T))
        Debug.WriteLine("Prioritizing Schedule of " & GetType(T).Name)
        ...
    End Sub
End Module

The Prioritize method first includes a type list indicating that it generically depends on a type named T within this method. It then includes the extension method parameter list. The first parameter (the only parameter in this example) gives the class that the method extends: Schedule(Of T).

The following code fragment shows how a program could create a Schedule of Job objects and then call the Prioritize extension:

Dim sched As New Schedule(Of Job)
...
sched.Prioritize()

Generic extension methods can become extremely complicated. For more detailed information about extension methods in general, see Chapter 16, “Subroutines and Functions,” and the Microsoft Visual Basic Team blog post at http://blogs.msdn.com/vbteam/pages/articles-about-extension-methods.aspx, paying special attention to Part 5, “Generics and Extension Methods.”

GENERIC METHODS

In addition to generic classes and extension methods, you can create generic methods. This is simply a method that takes generic parameters. The following code shows a Switcher class that has a shared generic Switch method:

Public Class Switcher
    Public Shared Sub Switch(Of T)(ByRef thing1 As T, ByRef thing2 As T)
        Dim temp As T = thing1
        thing1 = thing2
        thing2 = temp
    End Sub
End Class

The Switcher class is not generic, but it contains a generic method. Both generic and non-generic classes can define both generic and non-generic methods. For example, the following code shows a code module that contains a generic Switch method:

Module SwitchStuff
    ' Switch two variables' values.
    Public Sub Switch(Of T)(ByRef thing1 As T, ByRef thing2 As T)
        Dim temp As T = thing1
        thing1 = thing2
        thing2 = temp
    End Sub
End Module

The only difference between this code and the previous version is that the previous version includes the Shared keyword so the program can use the class’s method without instantiating the class.

PROHIBITED GENERICS

Unfortunately (or perhaps fortunately because this could be extremely complicated and confusing), you cannot make generic lambda functions. The following code shows a lambda function that is allowed and a generic lambda function that is not allowed:

' Allowed.
Dim max_index1 = Function(lst As List(Of Integer)) lst.Count - 1
 
' Prohibited.
Dim max_index2 = Function(Of T)(lst As List(Of T)) lst.Count - 1

You also cannot make generic properties, operators, events, or constructors.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.162.76