Home

Generics

Fundamentals of Generics

Introduction to Generic Procedures/Functions

Consider the following sub-procedure:

<script runat="server">
Sub Display(ByVal value As Object)
    Response.Write(value)
End Sub
</script>

This procedure takes a value and displays it. Here is an example of calling the procedure:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head>
<script runat="server">
Sub Display(ByVal value As Object)
    Response.Write(value)
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim a = 25

    Display(a)
%>
</body>
</html>

This would produce:

Introduction to Generic Procedures

Here is another example of calling the same procedure:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head>
<script runat="server">
Sub Display(ByVal value As Object)
    Response.Write(value)
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim m = "Social Sciences: Philosophy"

    Display(m)
%>
</body>
</html>

This would produce:

Introduction to Generic Procedures

The procedure doesn't restrict the type of value it can receive. This means that any value can be passed to the procedure/function. A generic procedure/function is one that involves one or more parameters without specifying the exact type of value the parameter(s) is(are) using but still carrying its(their) normal operation(s). Normally, at the time the procedure is created, it specifies its operation(s) or role(s) but doesn't restrict it(them) to one particular type. Only when the function is called is(are) the desired type(s) specified.

Creating a Generic Procedure or Function

A generic procedure or function must always take a (or at least one) parameter. When creating the procedure or function, to indicate that its parameter is not specified, in other words, to indicate that it is generic, specify it using the Of keyword followed by a letter or a word. The formula to follow is:

[ access-modifier(s) ] [ Shadows ] [ Sub | Function name(Of letter/word)(ByVal arg As letter/word)

Start by specifying which one of the sub-procedure or the function you want to create. This is followed by a name and two sets of parentheses. In the first set, use the Of keyword followed by a letter or a word, any letter or any non-keyword word. This is followed by a second set of parentheses in which you pass a parameter of the same letter or word of the first set of parentheses. Here is an example:

<script runat="server">
Sub Display(Of Something)(ByVal parameter As Something)

End Sub
</script>

Calling a Generic Procedure or Function

To call a generic procedure, simply pass the desired argument to it. Here is an example of calling the procedure by passing a number-based type:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script Language="VB" runat="server">
Public Sub Display(Of Something)(ByVal parameter As Something)
    Response.Write(parameter.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim m = 1245.50

    Display(m)
%>

</body>
</html>

This would produce:

Calling a Generic Procedure or Function

Here is another example of calling the same procedure passing an object:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Class Element
    Public AtomicNumber As Integer
    Public ChemicalSymbol As String
    Public ElementName As String
    Public AtomicMass As String
    Public Phase As String
    Public Appearance As String

    Public Introduction As String
    Public Conclusion As String

    Public Overrides Function ToString$()
        return Me.Introduction &  Environment.NewLine &
               "<p>" & ElementName & " has the following properties:</p>" & Environment.NewLine &
               "<ul>" & Environment.NewLine &
               "  <li>Chemical Symbol: " & ChemicalSymbol  & "</li>" & Environment.NewLine &
               "  <li>Atomic Number: " & AtomicNumber & "</li>" & Environment.NewLine &
               "  <li>Atomic Weight: " & AtomicMass  & "</li>" & Environment.NewLine &
               "  <li>Phase: " & Phase & "</li>" & Environment.NewLine &
               "  <li>Appearance: " & Appearance & "</li>" & Environment.NewLine &
               "</ul>" &  Environment.NewLine &        Me.Conclusion
    End Function
End Class

Public Sub Display(Of Something)(ByVal parameter As Something)
    Response.Write(parameter.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim c As Element = New Element

    c.Conclusion = "<p>While hydrogen is the dominant substance in the universe, carbon is " &
                          "the main component of most minerals such as diamond and graphite. Combining " &
                          "hydrogen and carbon results in many types of organic compounds.</p>"

    c.Introduction = "<p>Carbon is one of the most commonly found chemical components on earth. It " &
                            "can be found inside the earth, on the human body, and in many organic compounds. " &
                            "Carbon is the 6th most abundant chemical element on earth. The order of " &
                            "abundance is:</p>"
    c.AtomicNumber = 6
    c.ChemicalSymbol = "C"
    c.ElementName = "Carbon"
    c.AtomicMass = 12.011
    c.Phase = "Solid"
    c.Appearance = "Black"

    Display(c)
%>

</body>
</html>

This would produce:

Calling a Generic Procedure or Function

By tradition, the letter t (or T) is used for the Of parameter. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of t)(ByVal parameter As t)
    Response.Write(parameter.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim age As Integer
    Dim drinkingUnderAge As Boolean

    age = 21
    
    drinkingUnderAge = (age >= 21)

    Display(drinkingUnderAge )
%>

</body>
</html>

This would produce:

Calling a Generic Procedure or Function

A Procedure With Generic and Non-Generic Types

You can create a procedure or a function that uses a generic parameter and one or more parameters with (a) specific data type(s). Here is an example:

Public Sub Display(Of t)(ByVal m As String, ByVal arg As t)

End Sub

When calling the procedure, pass the arguments in the appropriate order and the right type. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Enum HouseTypes
    Condominium
    Townhouse
    SingleFamily
End Enum

Public Sub Display(Of t)(ByVal m As String, ByVal arg As t)
    Response.Write(arg.ToString() & "<br>" & m)
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim category As HouseTypes = HouseTypes.SingleFamily
    Dim description = "A single-family is a type of house that stands by itself. That is, it is not attached to another house."
    Display(description, category)

    Response.Write("<br>")
    Response.Write("<br>")

    Dim pi = 3.14156
    Dim descr = "The greek letter PI is used to calculate the area of a circle and related geometric figures such as the sphere."
    Display(descr, pi)
%>

</body>
</html>

This would produce:

A Procedure With Generic and Non-Generic Types

Passing Many Arguments to a Generic Procedure

A generic procedure can take more than one argument. When creating the procedure, if the parameters will use the same type, each parameter must use the common type specified in the first set of parentheses. In the second set of parentheses, specify each parameter but separate them with commas. Here is an example:

Public Sub Display(Of t)(ByVal a As t, ByVal b As t)

End Sub

When calling the procedure, pass the appropriate number of arguments and they must be of the same type. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u)(ByVal a As u, ByVal b As u)
    Response.Write(a.ToString() & ", " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim t As Boolean
    Dim f As Boolean

    t = True
    f = False

    Response.Write("Boolean Values: ")

    Display(t, f)
%>

</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

Here is another example of calling the same procedure:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u)(ByVal a As u, ByVal b As u)
    Response.Write(a.ToString() & "<br>" & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim linguistics = "<h3>Linguistics</h3>" &
                      "<p>Linguistics is the study of one or a family of languages. " &
                      "Linguistics studies the science, the technology, the mechanical, and physical " &
                      "aspects that rule a language. Linguistics scientifically describes the sound (and " &
                      "justifies the creation of the sound) produced when a particular " &
                      "language is spoken, how, and usually why a certain sound is produced.</p>"

    Dim anthropology = "<h3>Biology</h3>" &
                       "<p>Biology is the study of the existence of living " &
                       "organisms. Biology studies how the organisms start (such as how an organism " &
                       "is born), how they grow (or how they change from one state or phase to " &
                       "another), how they live, how they function, where they dwell, and how their " &
                       "existence ends (such as how they die). Biology can be divided in various " &
                       "fields of studies.</p>"

    Display(linguistics, anthropology)
%>

</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

Here is another example of calling the same procedure:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u)(ByVal a As u, ByVal b As u)
    Response.Write(a.ToString() & " : " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim ratio1 = 5
    Dim ratio2 = 3

    Response.Write("We need to distribute 6500 in the ratio ")

    Display(ratio1, ratio2)
%>

</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

If the arguments must be of different types, when creating the procedure or function, in the first set of parentheses, after the Of keyword, use different letters or words separated by commas. Use the same letters or words in the same order in the second set of parentheses for the parameters. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u, v)(ByVal a As u, ByVal b As v)
    Response.Write(a.ToString() & ": " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim m = "Long Sleeve Shirt"
    Dim n = 108.95
    Display(m, n)
%>
</body>
</html>

This would produce:

Passing Generic Arguments

Here is another example of calling the same procedure:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u, v)(ByVal a As u, ByVal b As v)
    Response.Write(a.ToString() & ": " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim t = True
    Dim o = 1
    Display(t, o)
%>
</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

In the same way, you can create a generic procedure with as many parameters as you want. You can also create a procedure or function that takes a combination of generic and non-generic parameters.

Generic Classes

Introduction

A class can have one or more members whose type(s) is(are) not known at the time the class is created. This is typical for a class that would be used to create a list. That is, you may want to create a list-based class (also called a collection class) that can be used to create lists of any types.

A generic class is one whose main member (property) type is not known in advance.

Creating a Generic Class

To create a generic class, add some parentheses after the name of the class. In the parentheses, type Of followed by a letter or a word. Here is an example:

<script runat="server">
Class Occurrence(Of t)

End Class
</script>

You can then add the necessary members, such as a default constructor (a constructor with empty parentheses), properties and methods. Here are examples:

<script runat="server">
Class Occurrence(Of t)
    Public Sub New()

    End Sub

    Public Sub Remember()
        My.Response.Write("This is a generic class.")
    End Sub
End Class
</script>

Creating an Object From a Generic Class

When creating an object from a generic class, if you have a default constructor, you must add the parentheses to the name of the class applied to the New operator. Even if the class doesn't have a default constructor, you must add empty parentheses to the name of the class. In the parentheses, type Of followed by the type of the value you are planning to use. You can then use the object to access the members of the class. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Class Occurrence(Of t)
    Public Sub Remember()
        My.Response.Write("This is a generic class.")
    End Sub
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim incremental As New Occurrence(Of Integer)
    Dim period As New Occurrence(Of String)
    Dim national As New Occurrence(Of Date)

    incremental.Remember()
    Response.Write("<br>")
    period.Remember()
%>
</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

A Generic Field

A generic field is a member variable that uses the letter or the word of the Of clause as its type. Here is an example:

<script runat="server">
Class Occurrence(Of t)
    ' A generic field
    Private gen As t
End Class
</script>

Such a field can be accessed by any member of the class, whether the member indicates that it uses the generic type or not. Here is an example:

<script runat="server">
Class Occurrence(Of t)
    ' A generic field
    Private gen As t

    Public Sub Relate()
        My.Response.Write(gen.ToString())
    End Sub
End Class
</script>

A Generic Property

A property is generic if it uses the letter or the word of the Of clause as its type. If the property auto-implements, there is no further action you need to take. For a read-write property, you should first create a field of the same type and use that field in your property. You can then use the property like any other. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Class Occurrence(Of t)
    ' A generic field
    Private gen As t

    ' A generic property
    Public Property Occurs As t
        Get
            Return gen
        End Get
        Set(ByVal value As t)
            gen = value
        End Set
    End Property

    Public Sub Relate()
        My.Response.Write(gen.ToString())
    End Sub
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim incremental As New Occurrence(Of Integer)
    Dim period As New Occurrence(Of String)
    Dim national As New Occurrence(Of Date)

    incremental.Occurs = 1
    Response.Write("First day of every month: ")
    incremental.Relate()
    
    Response.Write("<br>")
    period.Occurs = "01/01/1901"
    Response.Write("Australia Independence: ")
    period.Relate()

    Response.Write("<br>")
    national.Occurs  = New DateTime(1975, 11, 11)
    Response.Write("Angola National Day: ")
    national.Relate()
%>
</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

A Generic Method

A method or a constructor of a class can be generic. When creating the method, pass one or more parameter that use the letter or the word of the Of keyword as parameter. Other than that, follow the normal rules for procedures. Here are examples:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Class Occurrence(Of t)
    ' A generic field
    Private gen As t

    Public Sub New()

    End Sub

    Public Sub New(ByVal arg As t)
        Me.gen = arg
    End Sub

    Public Sub Relate()
        My.Response.Write(gen.ToString())
    End Sub

    Public Sub Relate(ByVal a As t, ByVal b As t)
        My.Response.Write(a.ToString() & " at " & b.ToString())
    End Sub
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim days As New Occurrence(Of Integer)(30)
    Dim war As New Occurrence(Of String)

    Response.Write("The months of April, Juin, September, and November have ")
    days.Relate()
    Response.Write(" days.")

    Response.Write("<br>The attack on Pearl Harbor started on ")
    war.Relate("07/12/1941", "07:48 AM")
    Response.Write(" local time.")
%>
</body>
</html>

This would produce:

Passing Many Arguments to a Generic Procedure

A Generic Class With Various Types

As seen with procedures, a generic class can use different generic types. To specify those types, in the parentheses of creating the class, type Of followed by a letter or a word for each type of value but seperate them with commas. Here is an example:

<script runat="server">
Class Combination(Of u, v)

End Class
</script>

When creating an object from the class, in the parentheses of the name of the class, type Of followed by each type but separate them with commas. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Class Combination(Of u, v)

End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim combo As New Combination(Of Integer, String)
%>
</body>
</html>

In the body of the class, you don't have to use any of the types. In fact, you may decide to use only one of them. In this case, create the members that would need a value for that type. If you create a constructor uses only one of the types, when declaring a variable, add a set of parentheses to the class on the variable and add the value for the type. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Class Combination(Of u, v)
    Private intro As u
    Private define As v

    Public Sub New(ByVal a As u)
        Me.intro = a
    End Sub

    Public Property Introduction As u
        Get
            Return intro
        End Get
        Set(ByVal value As u)
            intro = value
        End Set
    End Property

    Public Sub Relate()
        My.Response.Write(intro.ToString())
    End Sub
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim midday As New Combination(Of Integer, String)(12)

    Response.Write("Midday is at ")
    midday.Relate()
%>
</body>
</html>

This would produce:

A Generic Class With Various Types

Otherwise, you can use all types specified in the Of clause. Here are examples:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Class Combination(Of u, v)
    Private intro As u
    Private define As v

    Public Sub New()

    End Sub

    Public Sub New(ByVal a As u, ByVal b As v)
        Me.intro = a
        Me.define = b
    End Sub

    Public Property Introduction() As u
        Get
            Return intro
        End Get
        Set(ByVal value As u)
            intro = value
        End Set
    End Property

    Public Property Definition() As v
        Get
            Return define
        End Get
        Set(ByVal value As v)
            define = value
        End Set
    End Property

    Public Sub Show()
        My.Response.Write(intro.ToString() & ", " & define.ToString())
    End Sub

    Public Sub Show(ByVal a As u, ByVal b As v)
        My.Response.Write(a.ToString() & ", " & b.ToString())
    End Sub
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim war As New Combination(Of String, Date)

    war.Introduction = "World War II"
    war.Definition = New DateTime(1939, 09, 01)
    Response.Write("Event: ")
    war.Show()

    Dim values As New Combination(Of Integer, Boolean)()
    Response.Write("<br>Some values: ")
    values .Show(40, False)

    Dim employee As New Combination(Of Integer, String)(826048, "James Brauer")
    Dim work As New Combination(Of Date, Double)(New DateTime(2017, 6, 10), 9.50)

    Response.Write("<p>Employee: ")
    employee.Show()
    Response.Write("<br>Work Day: ")
    work.Show()
    Response.Write("</p>")
%>
</body>
</html>

This would produce:

A Generic Class With Various Types

Constraints on Generics

All of the generic procedures and classes we have used so far could take any type. In some cases, when creating a generic function or a generic class, you may want to restrict the types of values that can be used on the generic parameter. Putting a restriction on a generic parameter is referred to as constraining the generic type. Generic constraining is done using the As keyword.

To indicate that a parameter type of a generic procedure/function or a generic class must be based on a certain type, after the letter or word of the Of clause, add As followed by the desired type. In the body of the generic procedure or generic class, use the parameter based on the rules of its restricted type. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">
Public Class Numeric
    Private oper1 As Double
    Private oper2 As Double

    Public Sub New(ByVal a As Double, ByVal b As Double)
        oper1 = a
        oper2 = b
    End Sub

    Public Function Add()
        Return oper1 + oper2
    End Function

    Public Function Multiply()
        Return oper1 * oper2
    End Function

    Public Function Subtract()
        Return oper1 - oper2
    End Function

    Public Function Divide()
        If oper2 = 0 Then
            Return 0
        Else
            Return oper1 / oper2
        End If
    End Function
End Class

Public Sub Display(Of t As Numeric)(ByVal parameter As t)
    Response.Write(parameter.Add())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
    Dim number As New Numeric(1560, 280)

    Response.Write("1560 + 280 = ")
    Display(number)
%>
</body>
</html>

This would produce:

Constraints on Generics


Previous Copyright © 2014-2016, FunctionX Next