Delegates |
|
Fundamentals of Delegates
Introduction to Delegates
A delegate is a special type of user-defined variable that is declared globally, like a class. A delegate provides a prototype for a procedure, a function, or a method. Like an interface, a delegate is not defined. Its role is to provide a syntax for a procedure or a function.
As you should know already, the Visual Basic language has two categories of procedures: sub-procedures and functions. Delegates also distinguish them. The basic formula to create a delegate for a sub-procedure is:
[modifier] Delegate Sub name ()
The modifier can be Public, Private, or Friend. The Delegate keyword is required. The name must be a valid name for a procedure or a function. Because a delegate represents a procedure, it must use parentheses. If the procedure will not take any argument, leave the parentheses empty.
Here is an example of creating a delegate:
Delegate Sub Definition()
Remember that a delegate only provides a template for a procedure, not an actual function. Before using it, you must define a procedure that would carry an assignment. Here is an example:
<script runat="server"> Public Sub Describe() Response.Write("<p>The metric system is a set of rules that provide " & "common standards for different countries, organizations, " & "and cultures to share numeric values. The values address " & "length, mass, and time.</p>") End Sub </script>
After implementing the procedure, you can associate it to the delegate. To do that, where you want to use the procedure, declare a variable of the type of the delegate. Here is an example:
<%
Dim metric As Definition
%>
To initialize the variable, use the New operator followed by the name of the delegate and parentheses. In the parentheses, you must access the procedure by its address. To let you do this, the Visual Basic language provides the AddressOf operator. It is followed by the name of the procedure. Once a delegate has been made aware of the procedure that implements it, you can use the variable as if calling a procedure. That is, you can write the name of the variable followed by parentheses. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Delegate Sub Definition()
Public Sub Describe()
Response.Write("<p>The metric system is a set of rules that provide " &
"common standards for different countries, organizations, " &
"and cultures to share numeric values. The values address " &
"length, mass, and time.</p>")
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim metric As Definition
metric = New Definition(AddressOf Describe)
metric()
%>
</body>
</html>
This would produce:
As it is possible in Visual Basic, you don't have to separately declare the variable and initialize it. You can use the As New clause to declare and initialize the variable. Here is an example:
<%
Dim metric As New Definition(AddressOf Describe)
metric()
%>
A Delegate With a Parameter for a Sub-Procedure
When necessary, a delegate can take one or more parameters. The basic formula to create a delegate that takes a parameter is:
[modifier] Delegate Sub name (parameter(s))
Based on this, in the parentheses of the delegates, specify the parameter by its name and its type. When creating the related procedure, you must also specify the same type of parameter. When calling the associate variable, make sure you pass an appropriate value for the argument. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Sub Performance(ByVal value As Double) Public Sub ShowCalculation(ByVal a As Double) Dim result = a * a Response.Write("<p>The squared value of " & a & " is " & result & "</p>") End Sub </script> <title>Exercise</title> </head> <body> <% Dim number As New Performance(AddressOf ShowCalculation) Dim nbr = Rnd * 1000 number(nbr) %> </body> </html>
This would produce:
A Delegate With Many Parameters for a Sub-Procedure
You can pass as many parameters as you need to a delegate. When creating the associated procedure, make sure you specify the same number, type, and order of parameters. When calling the procedure on the variable, make sure you pass the same number, type, and order of arguments. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Sub Plus(ByVal operand1 As Integer, ByVal operand2 As Integer) Public Sub ShowAddition(ByVal a As Integer, ByVal b As Integer) Dim result = a + b Response.Write("<p>" & a & " + " & b & " = " & result & "</p>") End Sub </script> <title>Exercise</title> </head> <body> <% Dim two As New Plus(AddressOf ShowAddition) Dim m = CInt(Int((10000 * Rnd()) + 1)) Dim n = CInt(Int((10000 * Rnd()) + 1)) two(m, n) %> </body> </html>
This would produce:
Of course, the parameters can be of different types. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Structure Employee Dim Identifier As String Dim FullName As String End Structure Delegate Sub Summary(ByVal a As String, ByVal b As Double) Function CreateEmployees() As Collection Dim workers As New Collection() workers.Add(New Employee() With {.Identifier = "80485", .FullName = "Roland Neuer"}) workers.Add(New Employee() With {.Identifier = "57364", .FullName = "Catherine Draney"}) workers.Add(New Employee() With {.Identifier = "20831", .FullName = "Aurhur Orender"}) workers.Add(New Employee() With {.Identifier = "37495", .FullName = "Bertha Gate"}) workers.Add(New Employee() With {.Identifier = "37597", .FullName = "Nestor Hinley"}) Return workers End Function Public Sub ShowPay(ByVal nbr As String, ByVal sales As Double) Dim salary As Double Dim empl As New Employee Dim employees = CreateEmployees() For Each empl In employees If empl.Identifier = nbr Then salary = sales * 12 / 100 Response.Write("Employee: " & nbr & " - " & empl.FullName) Response.Write("<br>Sales: " & sales) Response.Write("<br>Salary: " & FormatNumber(salary)) End If Next End Sub </script> <title>Exercise</title> </head> <body> <% Dim staff As Employee Dim pay As New Summary(AddressOf ShowPay) pay("20831", 18460) %> </body> </html>
This would produce:
In the same way, a delegate can take as many parameters as you want.
Actions Delegates
Introduction
Instead of making you create delegates from scratch, and to provide universal support for all .NET languages, the .NET Framework provides various pre-built or built-in delegates that you can use directly in your code. One of the built-in delegates is named Action. It is provided in various versions. The Action delegate is defined in the System namespace of the mscorlib.dll library.
Creating a Simple Action
The primary type of an Action delegate is for sub-procedures that take no parameter and return nothing. Its syntax is:
Public Delegate Sub Action
Notice that the syntax exactly resembles the one we saw in our introduction to delegates. This time, the name of the delegate is replaced with Action. Also notice that the Delegate Sub expression is used, exactly as it was in our introduction to delegates.
To create an action for the delegate, declare a variable. Since you would not have created a delegate, use Action to initialize the variable and add its parentheses. Here is an example:
<%
Dim metric As Action()
%>
The rest is done as we saw already. This means that you should first create a procedure. In the parentheses of Action, type AddressOf followed by the name of the procedure. Based on this description, this:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Sub Definition() Public Sub Describe() Response.Write("<p>The metric system is a set of rules that provide " & "common standards for different countries, organizations, " & "and cultures to share numeric values. The values address " & "length, mass, and time.</p>") End Sub </script> <title>Exercise</title> </head> <body> <% Dim metric As Definition metric = New Definition(AddressOf Describe) metric() %> </body> </html>
can be written as this:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub Describe()
Response.Write("<p>The metric system is a set of rules that provide " &
"common standards for different countries, organizations, " &
"and cultures to share numeric values. The values address " &
"length, mass, and time.</p>")
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim metric As Action
metric = New Action(AddressOf Describe)
metric()
%>
</body>
</html>
As it is possible in Visual Basic, you can declare and initialize the variable in one line. Here is an example:
<%
Dim metric As New Action(AddressOf Describe)
metric()
%>
</body>
</html>
An Action Delegate With a Parameter for a Sub-Procedure
Like regular delegates, the Action delegate can take a parameter. To support this, a version of this delegate uses the following syntax:
Public Delegate Sub Action(Of In T)(obj As T)
Notice that this Action delegate is generic. This means that it expects any type of value. As a result, when declaring the variable, you must indicate the type of value that will be used. This is done by adding a first set of parentheses to Action. In the parentheses, type Of followed by the type. Here is an example:
<%
Dim number As New Action(Of Integer)(AddressOf ...)
%>
In the second set of parentheses, type AddressOf followed by the procedure that implements the delegate. As a result, this:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Sub Performance(ByVal value As Double) Public Sub ShowCalculation(ByVal a As Double) Dim result = a * a Response.Write("<p>The squared value of " & a & " is " & result & "</p>") End Sub </script> <title>Exercise</title> </head> <body> <% Dim number As New Performance(AddressOf ShowCalculation) Dim nbr = Rnd * 1000 number(nbr) %> </body> </html>
is the same as:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub ShowCalculation(ByVal a As Double)
Dim result = a * a
Response.Write("<p>The squared value of " & a & " is " & result & "</p>")
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim number As New Action(Of Integer)(AddressOf ShowCalculation)
Dim nbr = Rnd * 1000
number(nbr)
%>
</body>
</html>
An Action Delegate With Parameters
To support parameters passed to a delegate, the Action delegate provides many versions, each for a certain number of parameters. The version that takes two arguments uses the following syntax:
Public Delegate Sub Action(Of In T1, In T2)(arg1 As T1, arg2 As T2)
This syntax is for a sub-procedure that takes two arguments. As you can see, the parameters are generic types. When calling Action, once again, add two sets of parentheses. In the first set, type Of followed by the types of values separated by commas. When calling the variable as a procedure, make sure you pass the right types of arguments. As a result, this:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Sub Plus(ByVal operand1 As Integer, ByVal operand2 As Integer) Public Sub ShowAddition(ByVal a As Integer, ByVal b As Integer) Dim result = a + b Response.Write("<p>" & a & " + " & b & " = " & result & "</p>") End Sub </script> <title>Exercise</title> </head> <body> <% Dim two As New Plus(AddressOf ShowAddition) Dim m = CInt(Int((10000 * Rnd()) + 1)) Dim n = CInt(Int((10000 * Rnd()) + 1)) two(m, n) %> </body> </html>
is equivalent to:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub ShowAddition(ByVal a As Integer, ByVal b As Integer)
Dim result = a + b
Response.Write("<p>" & a & " + " & b & " = " & result & "</p>")
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim two As New Action(Of Integer, Integer)(AddressOf ShowAddition)
Dim m = CInt(Int((10000 * Rnd()) + 1))
Dim n = CInt(Int((10000 * Rnd()) + 1))
two(m, n)
%>
</body>
</html>
Of course, the delegate (and its procedure) can take different types of arguments. To apply this, in the first set of parentheses of Action, type Of and the order of types. When calling the variable as a procedure, in its parentheses, make sure you provide the arguments in the appropriate order. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Structure Employee Dim Identifier As String Dim FullName As String End Structure Function CreateEmployees() As Collection Dim workers As New Collection() workers.Add(New Employee() With {.Identifier = "80485", .FullName = "Roland Neuer"}) workers.Add(New Employee() With {.Identifier = "57364", .FullName = "Catherine Draney"}) workers.Add(New Employee() With {.Identifier = "20831", .FullName = "Aurhur Orender"}) workers.Add(New Employee() With {.Identifier = "37495", .FullName = "Bertha Gate"}) workers.Add(New Employee() With {.Identifier = "37597", .FullName = "Nestor Hinley"}) Return workers End Function Sub ShowPay(ByVal nbr As String, ByVal sales As Double) Dim salary As Double Dim empl As New Employee Dim employees = CreateEmployees() For Each empl In employees If empl.Identifier = nbr Then salary = sales * 12 / 100 Response.Write("Employee: " & nbr & " - " & empl.FullName) Response.Write("<br>Sales: " & sales) Response.Write("<br>Salary: " & FormatNumber(salary)) End If Next End Sub </script> <title>Exercise</title> </head> <body> <% Dim pay As New Action(Of String, Double)(AddressOf ShowPay) pay("20831", 18460) %> </body> </html>
Delegates for Functions
Introduction
Another category of delegates focuses on functions. These are delegates that can produce a value. Remember that a delegate only provides a layout for a function but it not the function itself. As seen for procedures, you must have a function to which the delegate will point. Here is an example of a function:
<script runat="server"> Function Describe() As String Return "<p>Chemistry is the study of matter. Matter is the building block of anything in the environment. " & "Chemistry by examines the smallest object that starts a matter, which is the atom. Chemistry " & "explores the interactions between two atoms and among atoms. The study seeks to understand " & "how an atom of a kind, called a substance, combines with another atom of the same substance, " & "or how an atom of one substance combines with one or other atoms of other substances to produce " & "a new substance. A combination of atoms is also called a bond. The resulting object is called a " & "compound. Of course, there are rules that govern everything.</p>" End Function </script>
The basic formula to create a delegate for a parameter-less function is:
[modifier] Delegate Function name () As return-type
The approach is the same as seen for procedures. When creating the delegate, make it return the same type of value as the function. When declaring the variable, use the New operator to indicate the name of the delegate. In the parentheses, add the AddressOf operator followed by the name of the function. You can then use the variable as a function and get its returned value. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Function Introduction() As String Function Describe() As String Return "<p>Chemistry is the study of matter. Matter is the building block of anything in the environment. " & "Chemistry by examines the smallest object that starts a matter, which is the atom. Chemistry " & "explores the interactions between two atoms and among atoms. The study seeks to understand " & "how an atom of a kind, called a substance, combines with another atom of the same substance, " & "or how an atom of one substance combines with one or other atoms of other substances to produce " & "a new substance. A combination of atoms is also called a bond. The resulting object is called a " & "compound. Of course, there are rules that govern everything.</p>" End Function </script> <title>Chemistry</title> </head> <body> <% Dim lesson As New Introduction(AddressOf Describe) Response.Write(lesson()) %> </body> </html>
This would produce:
A Function Delegate With a Parameter
A function delegate can take a parameter, and the parameter can be any type you want. Make sure both the delegate and its associated function take the same type of parameter. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Function Estimation(ByVal number As Double) As Double Function Calculate(ByVal miles As Double) As Double Return miles * 0.46 End Function Sub btnCalculateClick() Handles btnCalculate.Click Dim result = 0.00 Dim distance As Double Dim salary As New Estimation(AddressOf Calculate) distance = If(String.IsNullOrEmpty(txtMiles.Text), 0.00, CDbl(txtMiles.Text)) result = salary(distance) txtGrossPay.Text = FormatNumber(result) End Sub </script> <title>Department Store</title> </head> <body> <form id="frmSalary" runat="server"> <table> <tr> <td>Miles Driven:</td> <td><asp:TextBox id="txtMiles" Width="65px" runat="server" /> <asp:Button id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick" runat="server" /> </td> </tr> <tr> <td>Gross Pay:</td> <td><asp:TextBox id="txtGrossPay" runat="server" /></td> </tr> </table> </form> </body> </html>
Here is an example of running the program:
A Function Delegate With Many Parameters
Instead of one parameter, a function delegate can take as many parameters as you want. For both the delegate and the associated function, make sure you follow the rules of passing arguments to a procedure or a function. Here are examples of delegates that each take two arguments of the same type:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Delegate Function Plus(ByVal a As Integer, ByVal b As Integer) As Integer Delegate Function Times(ByVal a As Integer, ByVal b As Integer) As Integer Delegate Function Over(ByVal a As Double, ByVal b As Double) As Double Public Function Add(ByVal a As Integer, ByVal b As Integer) As Integer Return a + b End Function Public Function Multiply(ByVal a As Integer, ByVal b As Integer) As Integer Return a * b End Function Public Function Divide(ByVal a As Double, ByVal b As Double) As Double If b = 0 Then Throw New DivideByZeroException("Division by 0 is not allowed.") Else Return a / b End If End Function Sub btnCalculateClick() Handles btnCalculate.Click Dim div = 0.0 Dim amount = 0.0 Dim totalRatio = 0 Dim ratio1, ratio2 As Integer Dim portion1, portion2 As Double Dim addition As New Plus(AddressOf Add) Dim multiplication As New Times(AddressOf Multiply) Dim division As New Over(AddressOf Divide) amount = If(String.IsNullOrEmpty(txtDistributedAmount.Text), 0.00, CDbl(txtDistributedAmount.Text)) ratio1 = If(String.IsNullOrEmpty(txtRatio1.Text), 0, CDbl(txtRatio1.Text)) ratio2 = If(String.IsNullOrEmpty(txtRatio2.Text), 0, CDbl(txtRatio2.Text)) totalRatio = addition(ratio1, ratio2) div = division(amount, totalRatio) portion1 = multiplication(div, ratio1) portion2 = multiplication(div, ratio2) txtPortion1.Text = FormatNumber(portion1) txtPortion2.Text = FormatNumber(portion2) End Sub </script> <title>Department Store - Financial Projections</title> </head> <body> <title>Department Store - Financial Projections</title> <p>Distribute the following amount of money between advertising and research in the indicated ratio</p> <form id="frmCompany" runat="server"> <table> <tr> <td>Amount to Distribute:</td> <td><asp:TextBox id="txtDistributedAmount" Width="65px" runat="server" /></td> </tr> <tr> <td>Ratio:</td> <td> <asp:TextBox id="txtRatio1" Width="25px" runat="server" />: <asp:TextBox id="txtRatio2" Width="25px" runat="server" /> <asp:Button id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick" runat="server" /></td> </tr> <tr> <td>Portion 1:</td> <td> <asp:TextBox id="txtPortion1" Width="65px" runat="server" /></td> </tr> <tr> <td>Portion 2:</td> <td> <asp:TextBox id="txtPortion2" Width="65px" runat="server" /></td> </tr> </table> </form> </body> </html>
Here is an example of running the program:
Of course, the parameters can use different types.
Functions Delegates
Introduction
Instead of maing you create delegate functions from scratch, to support functions and methods that return a value, the .NET Framework provides a delegate named Func. As seen for the Action type, the Func delegate is delivered in various versions that take different parameters.
A Simple Function
The most fundamental version of a function delegate uses the following syntax:
Public Delegate Function Func(Of Out TResult) As TResult
This time, instead of the Action word, Func is used. This version is for a function or method that takes no parameter but returns a value. The return value is a generic type. This means that you must specify the type of value that the function or method must return. To use this version of the function, don't declare a delegate. In the section where you need it, declare a variable an initialize it using Func preceded by the New operator. As seen with the action delegate, Func is followed by two sets of parentheses. The first set contains Of followed by the return type of the function. In the second set, type AddressOf followed by the name of the function you want to use. You can then use the variable as when calling a function that returns a value. For example, you can assign it to a variable. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Function Describe() As String Return "<p>Chemistry is the study of matter. Matter is the building block of anything in the environment. " & "Chemistry by examines the smallest object that starts a matter, which is the atom. Chemistry " & "explores the interactions between two atoms and among atoms. The study seeks to understand " & "how an atom of a kind, called a substance, combines with another atom of the same substance, " & "or how an atom of one substance combines with one or other atoms of other substances to produce " & "a new substance. A combination of atoms is also called a bond. The resulting object is called a " & "compound. Of course, there are rules that govern everything.</p>" End Function </script> <title>Chemistry</title> </head> <body> <% Dim leçon As String Dim lesson As New Func(Of String)(AddressOf Describe) leçon = lesson() Response.Write(leçon) %> </body> </html>
If you don't need to use the return value many times, you don't have to store it in a variable. You can call it directly where the return value is needed. Here is an example:
<%
Dim lesson As New Func(Of String)(AddressOf Describe)
Response.Write(lesson())
%>
In the same way, you don't have to formally declare a variable for Func. You can use and call it directly where needed. Here is an example:
<%
Response.Write((New Func(Of String)(AddressOf Describe))())
%>
A Function Delegate With a Parameter
Like a procedure, a function delegate can take a parameter, of any type. To support this, the overloaded Func delegate has a version whose syntax is:
Public Delegate Function Func(Of In T, Out TResult)(arg As T) As TResult
Of course, you must have a function that takes one parameter. When declaring the variable, after the Func keyword and its parentheses, in the first set, type Of followed by the type of the argument, a comma, and the return type of the function. When calling the variable as a function, pass the argument as the first type of Func. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Function Calculate(ByVal miles As Double) As Double
Return miles * 0.46
End Function
Sub btnCalculateClick() Handles btnCalculate.Click
Dim result = 0.00
Dim distance As Double
Dim salary As New Func(Of Double, Double)(AddressOf Calculate)
distance = If(String.IsNullOrEmpty(txtMiles.Text), 0.00, CDbl(txtMiles.Text))
result = salary(distance)
txtGrossPay.Text = FormatNumber(result)
End Sub
</script>
<title>Department Store</title>
</head>
<body>
<form id="frmSalary" runat="server">
<table>
<tr>
<td>Miles Driven:</td>
<td><asp:TextBox id="txtMiles" Width="65px" runat="server" />
<asp:Button id="btnCalculate" Text="Calculate"
OnClick="btnCalculateClick" runat="server" /> </td>
</tr>
<tr>
<td>Gross Pay:</td>
<td><asp:TextBox id="txtGrossPay" runat="server" /></td>
</tr>
</table>
</form>
</body>
</html>
Remember that the syntax of Func indicates that the first parameter is the actual argument while the second it the return type. This means that you must make sure you specify the types in the right order of Func and the pass the right type of argument when accessing the variable as a function. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Function Identify(ByVal nbr As Integer) As String
Dim shape As String
If nbr = 3 Then
shape = "an equilateral triangle"
Else If nbr = 4 Then
shape = "a square"
Else If nbr = 5 Then
shape = "a pentagon"
Else If nbr = 6 Then
shape = "a hexagon"
Else If nbr = 7 Then
shape = "a heptagon"
Else If nbr = 8 Then
shape = "an octagon"
Else
shape = "Unknown Shape"
End If
Return shape
End Function
</script>
<title>Geometry - Polygons</title>
</head>
<body>
<%
Dim sides = 5
Dim geometry As New func(Of Integer, String)(AddressOf Identify)
Response.Write("<p>A polygon with " & sides & " sides is called " & geometry(sides) & ".</p>")
%>
</body>
</html>
This would produce:
If you pass the arguments in the wrong order, you may get unpredictable results or receive an error.
A Function Delegate With Many Parameters
To support function delegates that takes various parameters, the Func delegate is overloaded with various versions. The version with two parameters has the following syntax:
Public Delegate Function Func(Of In T1, In T2, Out TResult)(arg1 As T1, arg2 As T2) As TResult
If the parameters are the same type, the delegate and its variable can be easy to use. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Function Add(ByVal a As Integer, ByVal b As Integer) As Integer Return a + b End Function Public Function Multiply(ByVal a As Integer, ByVal b As Integer) As Integer Return a * b End Function Public Function Divide(ByVal a As Double, ByVal b As Double) As Double If b = 0 Then Throw New DivideByZeroException("Division by 0 is not allowed.") Else Return a / b End If End Function Sub btnCalculateClick() Handles btnCalculate.Click Dim div = 0.0 Dim amount = 0.0 Dim totalRatio As Integer Dim ratio1, ratio2 As Integer Dim portion1, portion2 As Double Dim addition As New Func(Of Integer, Integer, Integer)(AddressOf Add) Dim multiplication As New Func(Of Integer, Integer, Integer)(AddressOf Multiply) Dim division As New Func(Of Double, Double, Double)(AddressOf Divide) amount = If(String.IsNullOrEmpty(txtDistributedAmount.Text), 0.00, CDbl(txtDistributedAmount.Text)) ratio1 = If(String.IsNullOrEmpty(txtRatio1.Text), 0, CDbl(txtRatio1.Text)) ratio2 = If(String.IsNullOrEmpty(txtRatio2.Text), 0, CDbl(txtRatio2.Text)) totalRatio = addition(ratio1, ratio2) div = division(amount, totalRatio) portion1 = multiplication(div, ratio1) portion2 = multiplication(div, ratio2) txtPortion1.Text = FormatNumber(portion1) txtPortion2.Text = FormatNumber(portion2) End Sub </script> <title>Department Store - Financial Projections</title> </head> <body> <title>Department Store - Financial Projections</title> <p>Distribute the following amount of money between advertising and research in the indicated ratio</p> <form id="frmCompany" runat="server"> <table> <tr> <td>Amount to Distribute:</td> <td><asp:TextBox id="txtDistributedAmount" Width="65px" runat="server" /></td> </tr> <tr> <td>Ratio:</td> <td> <asp:TextBox id="txtRatio1" Width="25px" runat="server" />: <asp:TextBox id="txtRatio2" Width="25px" runat="server" /> <asp:Button id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick" runat="server" /></td> </tr> <tr> <td>Portion 1:</td> <td> <asp:TextBox id="txtPortion1" Width="65px" runat="server" /></td> </tr> <tr> <td>Portion 2:</td> <td> <asp:TextBox id="txtPortion2" Width="65px" runat="server" /></td> </tr> </table> </form> </body> </html>