Delegates |
|
The C and C++ languages have long used the concept of function pointer. This was even more useful when programming for the Microsoft Windows operating systems because the Win32 library relies on the concept of callback functions. Callback functions are used in Microsoft Windows programming to process messages. For this reason and because of their functionality, callback functions were carried out in the .NET Framework but they were defined with the name of delegate. A delegate is a special type of user-defined variable that is declared globally, like a class. A delegate provides a template for a method, like an interface provides a template for a class. Like an interface, a delegate is not defined. Its role is to show what a useful method would look like. To support this concept, a delegate can provide all the necessary information that would be used on a method. This includes a return type, no argument or one or more arguments. |
Practical Learning: Introducing Delegates |
using System; namespace WattsALoan1 { class LoanEvaluation { public double GetPrincipal() { Console.Write("Enter the Principal: $"); double P = double.Parse(Console.ReadLine()); return P; } public double GetInterestRate() { Console.Write("Enter the Interest Rate (%): "); double r = double.Parse(Console.ReadLine()); return r; } public int GetPeriod() { Console.Write("Enter the number of months: "); int t = int.Parse(Console.ReadLine()); return t; } } } |
using System; namespace WattsALoan1 { class Program { static int Main() { int NumberOfPeriods; double Principal, IntRate; LoanEvaluation loan = new LoanEvaluation(); Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); Console.WriteLine("Loan Processing\n"); Console.WriteLine("This program allows you to calculate the amount of money a "); Console.WriteLine("customer will owe at the end of the lifetime of a loan\n"); Principal = loan.GetPrincipal(); IntRate = loan.GetInterestRate(); NumberOfPeriods = loan.GetPeriod(); Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); Console.WriteLine("================================"); Console.WriteLine("Loan Estimation"); Console.WriteLine("--------------------------------"); Console.WriteLine("Principal: {0:C}", Principal); Console.WriteLine("Interest: {0:P}", IntRate / 100); Console.WriteLine("Period: {0} months", NumberOfPeriods); Console.WriteLine("================================\n"); return 0; } } } |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Loan Processing This program allows you to calculate the amount of money a customer will owe at the end of the lifetime of a loan Enter the Principal: $14500 Enter the Interest Rate (%): 12.25 Enter the number of months: 48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ================================ Loan Estimation -------------------------------- Principal: $14,500.00 Interest: 12.25 % Period: 48 months ================================ Press any key to continue . . . |
using System; namespace WattsALoan1 { class LoanEvaluation { public double GetPrincipal() { Console.Write("Enter the Principal: $"); double P = double.Parse(Console.ReadLine()); return P; } public double GetInterestRate() { Console.Write("Enter the Interest Rate (%): "); double r = double.Parse(Console.ReadLine()); return r; } public void GetPeriod(ref int TypeOfPeriod, ref int Periods) { Console.WriteLine("How do you want to enter the length of time?"); Console.WriteLine("1 - In Days"); Console.WriteLine("2 - In Months"); Console.WriteLine("3 - In Years"); Console.Write("Your Choice: "); TypeOfPeriod = int.Parse(Console.ReadLine()); if (TypeOfPeriod == 1) { Console.Write("Enter the number of days: "); Periods = int.Parse(Console.ReadLine()); } else if (TypeOfPeriod == 2) { Console.Write("Enter the number of months: "); Periods = int.Parse(Console.ReadLine()); } else if (TypeOfPeriod == 3) { Console.Write("Enter the number of years: "); Periods = int.Parse(Console.ReadLine()); } else { TypeOfPeriod = 0; // The user made an invalid selection. So, we will give up Console.WriteLine("Bad Selection\n"); } } } } |
using System; namespace WattsALoan1 { class Program { static int Main() { int Periods = 0; int TypeOfPeriod = 0; double Principal, IntRate; string PeriodName = null; LoanEvaluation loan = new LoanEvaluation(); Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); Console.WriteLine("This program allows you to calculate the amount of money a "); Console.WriteLine("customer will owe at the end of the lifetime of a loan\n"); Console.WriteLine("Loan Processing\n"); Principal = loan.GetPrincipal(); IntRate = loan.GetInterestRate(); loan.GetPeriod(ref TypeOfPeriod, ref Periods); if (TypeOfPeriod == 0) { // Since the user made a bad selection, stop the program here return 0; } // Since this "if" condition has a "return 0" line, if the "if" // condition produces true, the "return 0" means the function // would be terminated. If the condition is false, the inside of // this "if" condition would not execute and the function would // continue. This means that, if the condition is false, then // the "else' is implied. Therefore, we don't have to write an // "else" condition: it is automatic. if (TypeOfPeriod == 1) { PeriodName = "days"; } else if (TypeOfPeriod == 2) { PeriodName = "months"; } else if (TypeOfPeriod == 3) { PeriodName = "years"; } Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); Console.WriteLine("=================================="); Console.WriteLine("Loan Estimation"); Console.WriteLine("----------------------------------"); Console.WriteLine("Principal: {0:C}", Principal); Console.WriteLine("Interest: {0:P}", IntRate / 100); Console.WriteLine("Period: {0} {1}", Periods, PeriodName); Console.WriteLine("==================================\n"); return 0; } } } |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% This program allows you to calculate the amount of money a customer will owe at the end of the lifetime of a loan Loan Processing Enter the Principal: $7500.00 Enter the Interest Rate (%): 8.75 How do you want to enter the length of time? 1 - In Days 2 - In Months 3 - In Years Your Choice: 3 Enter the number of years: 4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ================================== Loan Estimation ---------------------------------- Principal: $7,500.00 Interest: 8.75 % Period: 4 years ================================== Press any key to continue . . . |
Creating a Delegate |
To create a delegate, you use the delegate keyword. The basic formula used to create a delegate is: [attributes] [modifiers] delegate ReturnType Name ([formal-parameters]);
Here is an example: using System; delegate void dlgSimple(); class Exercise { static int Main() { return 0; } } After declaring a delegate, remember that it only provides a template for a method, not an actual method. In order to use it, you must define a method that would carry an assignmentto perform. That method must have the same return type and the same (number of) argument(s), if any. For example, the above declared delegate is of type void and it does not take any argument. you can define a corresponding method as follows: using System; delegate void dlgSimple(); class Exercise { private static void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } static int Main() { return 0; } } With such a method implemented, you can associate it to the name of the delegate. To do that, where you want to use the method, first declare a variable of the type of the delegate using the new operator. In the parentheses of the constructor, pass the name of the method. Here is an example using System; delegate void dlgSimple(); class Exercise { private static void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } static int Main() { dlgSimple Announce = new dlgSimple(Welcome); return 0; } } This declaration gives meaning to the declared delegate. To actually use the method, call the name of the delegate as if it were a defined method. Here is an example: using System; delegate void dlgSimple(); class Exercise { private static void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } static int Main() { dlgSimple Announce = new dlgSimple(Welcome); Announce(); return 0; } } This would produce: Welcome to the Wonderful World of C# Programming! You can also declare a delegate that returns a value. When defining a method that would be associated with the delegate, remember that the method must return the same type of value. Here is an example: |
using System; delegate void dlgSimple(); delegate double Addition(); class Exercise { private static void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } private static double Plus() { double a = 248.66, b = 50.28; return a + b; } static int Main() { dlgSimple Announce = new dlgSimple(Welcome); Addition Add = new Addition(Plus); Announce(); Console.WriteLine("\n248.66 + 50.26 = {0}", Add()); return 0; } }
This would produce:
Welcome to the Wonderful World of C# Programming! 248.66 + 50.26 = 298.94
Practical Learning: Using a Delegate |
using System; namespace WattsALoan1 { class LoanEvaluation { public double GetPrincipal() { Console.Write("Enter the Principal: $"); double P = double.Parse(Console.ReadLine()); return P; } public double GetInterestRate() { Console.Write("Enter the Interest Rate (%): "); double r = double.Parse(Console.ReadLine()); return r; } public double GetPeriod(ref int TypeOfPeriod, ref double Periods) { Console.WriteLine("How do you want to enter the length of time?"); Console.WriteLine("1 - In Days"); Console.WriteLine("2 - In Months"); Console.WriteLine("3 - In Years"); Console.Write("Your Choice: "); TypeOfPeriod = int.Parse(Console.ReadLine()); if (TypeOfPeriod == 1) { Console.Write("Enter the number of days: "); Periods = double.Parse(Console.ReadLine()); return Periods / 360; } else if (TypeOfPeriod == 2) { Console.Write("Enter the number of months: "); Periods = double.Parse(Console.ReadLine()); return Periods / 12; } else if (TypeOfPeriod == 3) { Console.Write("Enter the number of years: "); Periods = double.Parse(Console.ReadLine()); return Periods; } else { TypeOfPeriod = 0; // The user made an invalid selection. So, we will give up Console.WriteLine("Bad Selection\n"); return 0.00; } } // Interest = Principal * rate * time in years public double InterestAmount(double P, double r, double t) { return P * (r / 100) * t; } } } |
using System; namespace WattsALoan1 { delegate double Add2Values(double Value1, double Value2); class Exercise { static int Main() { double Principal, IntRate, Period, AmountPaidAsInterest; int TypeOfPeriod = 0; double Periods = 0D; string PeriodName = null; LoanEvaluation loan = new LoanEvaluation(); Add2Values Add = new Add2Values(Addition); Console.WriteLine("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); Console.WriteLine("This program allows you to calculate the amount of money a "); Console.WriteLine("customer will owe at the end of the lifetime of a loan\n"); Console.WriteLine("Loan Processing\n"); Principal = loan.GetPrincipal(); IntRate = loan.GetInterestRate(); Period = loan.GetPeriod(ref TypeOfPeriod, ref Periods); AmountPaidAsInterest = loan.InterestAmount(Principal, IntRate, Period); double Amount = Add(Principal, AmountPaidAsInterest); if (TypeOfPeriod == 0) { // Since the user made a bad selection, stop the program here return 0; } // Since this "if" condition has a "return 0" line, if the "if" // condition produces true, the "return 0" means the function // would be terminated. If the condition is false, the inside of // this "if" condition would not execute and the function would // continue. This means that, if the condition is false, then // the "else' is implied. Therefore, we don't have to write an // "else" condition: it is automatic. if (TypeOfPeriod == 1) { PeriodName = "days"; } else if (TypeOfPeriod == 2) { PeriodName = "months"; } else if (TypeOfPeriod == 3) { PeriodName = "years"; } Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); Console.WriteLine("=================================="); Console.WriteLine("Estimate on loan"); Console.WriteLine("----------------------------------"); Console.WriteLine("Principal: {0:C}", Principal); Console.WriteLine("Interest: {0:P}", IntRate / 100); Console.WriteLine("Period: {0} {1}", Periods, PeriodName); Console.WriteLine("--------------------------------"); Console.WriteLine("Total Amount Paid: {0:C}", Amount); Console.WriteLine("Interest paid on Loan: {0:C}", AmountPaidAsInterest); Console.WriteLine("==================================\n"); return 0; } static double Addition(double Value1, double Value2) { return Value1 + Value2; } } } |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% This program allows you to calculate the amount of money a customer will owe at the end of the lifetime of a loan Loan Processing Enter the Principal: $12500 Enter the Interest Rate (%): 10.55 How do you want to enter the length of time? 1 - In Days 2 - In Months 3 - In Years Your Choice: 2 Enter the number of months: 42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ================================== Estimate on loan ---------------------------------- Principal: $12,500.00 Interest: 10.55 % Period: 42 months -------------------------------- Total Amount Paid: $17,115.63 Interest paid on Loan: $4,615.63 ================================== Press any key to continue . . . |
Delegates and Classes |
In the above introductions, we associated delegates with only method of the main class. Because delegates are usually declared globally, that is outside of a class, they can be associated with a method of any class, provided the method has the same return type (and the same (number of) argument(s)) as the delegate. When we created the methods of the main class, we defined them as static, since all methods of the main class must be declared static. Methods of any class can also be associated to delegates. Here is an example of two methods associated with a common delegate: |
using System; namespace CSharpLessons { delegate double Multiplication(); public class Cube { private double _side; public double Side { get { return _side; } set { _side = value; } } public Cube() { _side = 0; } public Cube(double s) { _side = s; } public double Area() { return 6 * Side * Side; } public double Volume() { return Side * Side * Side; } public void CubeCharacteristics() { Multiplication AreaDefinition = new Multiplication(Area); Multiplication VolDefinition = new Multiplication(Volume); Console.WriteLine("Cube Characteristics"); Console.WriteLine("Side: {0}", Side); Console.WriteLine("Area: {0}", AreaDefinition()); Console.WriteLine("Volume: {0}\n", VolDefinition()); } } class Exercise { static int Main() { Cube SmallBox = new Cube(25.58); SmallBox.CubeCharacteristics(); return 0; } } }
This would produce:
Cube Characteristics Side: 25.58 Area: 3926.0184 Volume: 16737.925112
Delegates Compositions |
One of the characteristics that set delegates apart from C/C++ function pointers is that one delegate can be added to another using the + operation. This is referred to as composition. This is done by adding one delegate variable to another as in a = b + c. |
|
||
Home | Copyright © 2006-2007 FunctionX, Inc. | Next |
|