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.
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]); The attributes factor can be a normal C# attribute. The modifier can be one or an appropriate combination of the following keywords: new, public, private, protected, or internal. The delegate keyword is required. The ReturnType can be any of the data types we have used so far. It can also be a type void or the name of a class. The Name must be a valid C# name. Because a delegate is some type of a template for a method, you must use parentheses, required for every method. If this method will not take any argument, leave the parentheses empty. Here is an example: using System; public delegate void Simple(); public class Program { static int Main() { return 0; } } After declaring a delegate, 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 assignment to 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: public delegate void Simple(); public class Exercise { public void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } } 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, declare a variable of the type of the delegate and assign the method to the delegate variable. Because you are assigning the method to a delegate, one of the rules of delegates is that you must not apply the parentheses to the method. Here is an example public class Program { static int Main() { Exercise exo = new Exercise(); Simple msg = exo.Welcome; return 0; } }
Once you have assigned a method to a delegate variable, you can use the delegate variable as if it were a defined method. That is, you can call it as you would proceed for a normal method. Here is an example: using System; using System.Collections.Generic; using System.Linq; using System.Text; public delegate void Simple(); public class Exercise { public void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } } namespace Delegates { public class Program { static int Main() { Exercise exo = new Exercise(); Simple msg = exo.Welcome; msg(); return 0; } } } This would produce: Welcome to the Wonderful World of C# Programming! Press any key to continue . . .
In the above example, we had to declare a variable of the (Exercise) class before accessing the method. An alternative is to create the associated method as static. That way, you would not need to declare the variable first. Here is an example: using System; public delegate void Simple(); public class Exercise { public static void Welcome() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); } } public class Program { static int Main() { Simple msg = Exercise.Welcome; msg(); return 0; } }
In the above examples, we had to create a method that would be associated with a delegate. As an alternative, you can create a delegate. Then, when you need to use it, create a type of local implementation of a method and use it. In other words, you do not have to explicitly define a method prior to using the delegate. Such a method is referred to as anonymous. Before implementing an anonymous method, first declare the delegate you will use: using System; public delegate void Simple(); public class Program { static int Main() { return 0; } } To create an anonymous method, declare a variable for the delegate and assign it the delegate keyword as if it were a method. That is, followed by parentheses and curly brackets that would represent the body of the method. In the body of the anonymous method, do whatever you want. Here is an example: using System; public delegate void Simple(); public class Program { static int Main() { Simple msg = delegate() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); }; return 0; } } Once you have done this, you can then call the delegate variable as if it were a normal method. Here is an example: using System; public delegate void Simple(); public class Program { static int Main() { Simple msg = delegate() { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); }; msg(); return 0; } }
You can also create an anonymous method using an operator called lambda and represented by =>. From our example above, to use the lambda operator to create an anonymous method, omit the delegate keyword and follow the parentheses by the operator. Here is an example: using System; public delegate void Simple(); public class Program { static int Main() { Simple msg = () => { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); }; return 0; } } Once you have done this, you can call the delegate variable as a method. Here is an example: using System; public delegate void Simple(); public class Program { static int Main() { Simple msg = () => { Console.WriteLine("Welcome to the Wonderful World of C# Programming!"); }; msg(); return 0; } }
You can create a delegate that returns a value. When creating the delegate, specify the data type to the left side of the name of the delegate. When defining a method that would be associated with the delegate, remember that the method must return the same type of value. In the body of the method, use it as you see fit. Before exiting the method, make sure you appropriately return a value. To use the method, follow the same approach as above. This time, when calling the delegate variable, you should use the parentheses. Here is an example: using System; delegate double Doubler(); public class Exercise { public static double MultiplyBy2() { return 255 * 2; } } public class Program { static int Main() { Doubler By2 = Exercise.MultiplyBy2; Console.WriteLine("Number = {0}", By2()); return 0; } } This would produce: Number = 510 Press any key to continue . . . In the same way, you can create an anonymous method that implements the delegate. To do this, follow the same rule we defined earlier. For example, you can use the delegate keyword. Here is an example: using System; delegate double Doubler(); public class Program { static int Main() { Doubler By2 = delegate() { return 255 * 2; }; Console.WriteLine("Number = {0}", By2()); return 0; } } Or you can use the lambda operator: using System; delegate double Doubler(); public class Program { static int Main() { Doubler By2 = () => { return 255 * 2; }; Console.WriteLine("Number = {0}", By2()); return 0; } }
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.
If you want to use a method that takes arguments and associate it to a delegate, when declaring the delegate, provide the necessary argument(s) in its parentheses. Here is an example of a delegate that takes two arguments (and returns a value): delegate double Doubler(double x); When defining the associated method, besides returning the same type of value if not void, make sure that the method takes the same number of arguments. Here is an example: public class Algebra { public static double MultiplyBy2(double a) { return a * 2; } }
To associate the method to the delegate, you can declare a variable for the delegate and assign the name of the method to it. Here is an example: using System; delegate double Doubler(double x); public class Algebra { public static double MultiplyBy2(double a) { return a * 2; } } public class Program { static int Main() { Doubler dbl = Algebra.MultiplyBy2; Console.WriteLine("Result = {0}", dbl); return 0; } } Notice that only the name of the method is passed to the delegate. To actually use the delegate, when calling it, add the parentheses to it and in the parentheses, provide a value for the argument(s). Here is an example: using System; delegate double Doubler(double x); public class Algebra { public static double MultiplyBy2(double a) { return a * 2; } } public class Program { static int Main() { Doubler dbl = Algebra.MultiplyBy2; Console.WriteLine("Result = {0}", dbl(248)); return 0; } } This would produce: Result = 496 Press any key to continue . . .
You can create an anonymous method for a delegate that takes one or more arguments. You can do this using the delegate keyword. In its parentheses, pass an argument that is the same type as the argument of the delegate. Then, in the body of the method, do what you judge necessary. When calling the variable of the delegate, use the same rules we have applied so far. Here is an example: using System; delegate double Doubler(double x); public class Program { static int Main() { Doubler dbl = delegate(double alpha) { return alpha * 2; }; Console.WriteLine("Result = {0}", dbl(248)); return 0; } } This technique of using the delegate keyword was introduced in C# 2.0 and has been updated with the lambda operator. Therefore, this was probably the last time we use it since we have been able to apply to different types of delegates. Instead of the delegate keyword, you can define an anonymous method using the lambda operator. In this case, in the parentheses of the lambda expression, enter the data type of the argument followed by its name. Here is an example: using System; delegate double Doubler(double x); public class Program { static int Main() { Doubler dbl = (double alpha) => { }; return 0; } } In the body of the anonymous method, use the argument as you see fit. Here is an example: using System; delegate double Doubler(double x); public class Program { static int Main() { Doubler dbl = (double alpha) => { return alpha * 2; }; return 0; } } After defining the method, you can call it like a normal method. Here is an example: using System; delegate double Doubler(double x); public class Program { static int Main() { Doubler dbl = (double alpha) => { return alpha * 2; }; Console.WriteLine("Result = {0}", dbl(248)); return 0; } } In our example, we specified the type of the argument. If you want, you can let the compiler figure out the type of argument. In this case, pass only the name of the argument and not its type. Here is an example: using System; delegate double Doubler(double x); public class Program { static int Main() { Doubler dbl = (alpha) => { return alpha * 2; }; Console.WriteLine("Result = {0}", dbl(248)); return 0; } }
A delegate can take more than one argument. To start, when declaring it, pass the desired number of arguments. If you will use a method to associate to the delegate, then create the method also. Here is an example: delegate double Addition(double x, double y); public class Algebra { public static double Plus(double a, double b) { return a + b; } } To use the delegate, follow the techniques we have applied so far and call the delegate as a method. Here is an example: using System; delegate double Addition(double x, double y); public class Algebra { public static double Plus(double a, double b) { return a + b; } } public class Exercise { static int Main() { Addition Operation = Algebra.Plus; Console.WriteLine("Result = {0}", Operation(52.04, 9.368)); return 0; } } This would produce: Result = 61.408 Press any key to continue . . . If you want to use a lambda expression to create an anonymous method, in its parentheses, pass the right number of arguments. In the body of the anonymous method, use the arguments ad you see fit. To use the delegate, call it as you would a normal method. Here is an example: using System; delegate double Addition(double x, double y); public class Exercise { static int Main() { Addition Operation = (x, y) => { return x + y; }; Console.WriteLine("Result = {0}", Operation(52.04, 9.368)); return 0; } }
Using delegates, one method can be indirectly passed as argument to another method. To proceed, first declare the necessary delegate. Here is a example of such a delegate: public delegate double Squared(double x); public class Circle { private double _radius; public double Radius { get { return _radius; } set { _radius = value; } } } A delegate can be passed as argument to a method. Such an argument would be used as if it were a method itself. This means that, when accessed in the body of the method, the name of the delegate must be accompanied by parentheses and if the delegate takes an argument or arguments, the argument(s) must be provided in the parentheses of the called delegate. Here is an example: public delegate double Squared(double x); public class Circle { private double _radius; public double Radius { get { return _radius; } set { _radius = value; } } public double Area(Squared sqd) { return sqd(_radius) * Math.PI; } } After declaring a delegate, remember to define a method that implements the needed behavior of that delegate. You can define the associated method in a class other than the one where the delegate would be used. Here is an example: using System; public class Exercise { public static double ValueTimesValue(double Value) { return Value * Value; } static int Main() { return 0; } } You can also define the method in the class where the delegate would be needed. Once the method that implements the delegate is known, you can use the delegate as you see fit. To do that, you can declare a variable of the type of that delegate and assign it to the variable. Here is an example: using System; public delegate double Squared(double x); public class Circle { private double _radius; public double Radius { get { return _radius; } set { _radius = value; } } public double Area(Squared sqd) { return sqd(_radius) * Math.PI; } } public class Exercise { public static double ValueTimesValue(double Value) { return Value * Value; } static int Main() { Squared Sq = ValueTimesValue; return 0; } } This declaration gives life to the delegate that can then be used as we have proceeded with delegates so far. Here is an example: using System; public delegate double Squared(double x); public class Circle { private double _radius; public double Radius { get { return _radius; } set { _radius = value; } } public double Area(Squared sqd) { return sqd(_radius) * Math.PI; } } public class Exercise { public static double ValueTimesValue(double Value) { return Value * Value; } static int Main() { Squared Sqr = ValueTimesValue; Console.WriteLine("Circle Area: {0}\n", Sqr(24.68)); return 0; } } This would produce: Circle Area: 609.1024 Press any key to continue . . . In the same way, you can use a lambda expression to implement an anonymous method that would be associated with a delegate. Here is an example: using System; public delegate double Squared(double x); public class Circle { private double _radius; public double Radius { get { return _radius; } set { _radius = value; } } public double Area(Squared sqd) { return sqd(_radius) * Math.PI; } } public class Exercise { static int Main() { Squared Sqr = (a) => { return a * a; }; Console.WriteLine("Circle Area: {0}\n", Sqr(24.68)); return 0; } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Delegates { public delegate void Message(); public class Circle { public Circle(Message sqr) { Console.WriteLine("That's the deal..."); } } public class Exercise { static void Show() { } static int Main(string[] args) { Circle circ = new Circle(new Message(Show)); return 0; } } }
So far, we have learned how to create and use delegate of primitive types. We learned how to create a void delegate, how to create a delegate that returns a value, and how to create a delegate that takes one or more argument. Just as a reminder, here is an example: using System; 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; } internal double Area() { return 6 * Side * Side; } internal double Volume() { return Side * Side * Side; } } public class Exercise { static int Main() { Cube SmallBox = new Cube(25.58); Multiplication AreaDefinition = SmallBox.Area; Multiplication VolDefinition = SmallBox.Volume; Console.WriteLine("Cube Characteristics"); Console.WriteLine("Side: {0}", SmallBox.Side); Console.WriteLine("Area: {0}", AreaDefinition); Console.WriteLine("Volume: {0}\n", VolDefinition); return 0; } } This would produce: Cube Characteristics Side: 25.58 Area: 3926.0184 Volume: 16737.925112
A delegate can be created to return a value that is of a class type. Of course you must know the class you want to use because the compiler would like to know the type of value that the delegate would return. You can use one of the many built-in classes of the .NET Framework or you can create your own class. When creating the delegate, specify the name of the class to its left as the returned type of value. Here is an example: delegate Person Creator(); public class Person { public string firstName; public string lastName; } After doing this, you can create a method that implements the delegate. The method must return the same type of value as the delegate. Here is an example: using System; delegate Person Creator(); public class Person { public string firstName; public string lastName; } public class Exercise { private static Person Create() { Person pers = new Person(); pers.firstName = "Julius"; pers.lastName = "Krands"; return pers; } } To use the delegate, declare a variable for it and assign the method to it. Here is an example: using System; delegate Person Creator(); public class Person { public string firstName; public string lastName; } public class Exercise { private static Person Create() { Person pers = new Person(); pers.firstName = "Julius"; pers.lastName = "Krands"; return pers; } static int Main() { Creator crt = Create; return 0; } } You can then call use the variable as you see fit. Instead of explicitly creating a method that implements the delegate, you can create an anonymous method using a lambda expression. In the body of the anonymous method, make sure you return a value of the type of the delegate. Here is an example: using System; delegate Person Creator(); public class Person { public string firstName; public string lastName; } public class Exercise { static int Main() { Creator Create = () => { var PersonalInformation = new Person(); PersonalInformation.firstName = "Julius"; PersonalInformation.lastName = "Krands"; return PersonalInformation; }; Create(); return 0; } }
A delegate can be created to receive a class type as argument. When creating the delegate, in its parentheses, specify the class whose value it takes as argument. Here is an example: using System; delegate void Anchor(Person p); public class Person { public string firstName; public string lastName; } To use the delegate, you can first create a method that implements the delegate, then declare a variable for the delegate and assign the method to it. If you prefer to create an anonymous method using a lambda expression, in the parentheses, enter a name for the argument and use that argument in the body of the method as you see fit. Here is an example: public class Exercise { static int Main() { Anchor personal = (individual) => { Console.WriteLine("=//= Personal Information =//="); Console.WriteLine("First Name: {0}", sample.firstName); Console.WriteLine("Last Name: {0}", sample.lastName); }; return 0; } } You can then call the method as you see fit. Here is an example: using System; delegate Person Creator(); delegate void Anchor(Person p); public class Person { public string firstName; public string lastName; } public class Exercise { static int Main() { var PersonalInformation = new Person(); Creator Create = () => { PersonalInformation.firstName = "Julius"; PersonalInformation.lastName = "Krands"; return PersonalInformation; }; Anchor personal = (individual) => { Console.WriteLine("=//= Personal Information =//="); Console.WriteLine("First Name: {0}", individual.firstName); Console.WriteLine("Last Name: {0}", individual.lastName); }; Create(); personal(PersonalInformation); return 0; } } This would produce: =//= Personal Information =//= First Name: Julius Last Name: Krands Press any key to continue . . . In the same way:
While a regular method can be used to return an array, you can use the features of a delegate to return an array of methods or to take an array of methods as arguments. Of course before proceeding, you must first create the necessary delegate. Here is an example: using System; delegate double Measure(double R); public static class Program { static int Main(string[] args) { return 0; } } Before creating the array, you must first know or have the methods you would be referring to. These methods must have a similar signature. This means that they must return the same type of value, they must have the same number of arguments and they must have the same type(s) of argument(s), if any. Here are examples of such functions: using System; delegate double Measure(double R); public class Circle { const double PI = 3.14159; double Diameter(double Radius) { return Radius * 2; } double Circumference(double Radius) { return Diameter(Radius) * PI; } double Area(double Radius) { return Radius * Radius * PI; } } public static class Program { static int Main(string[] args) { return 0; } }
To create an array of delegates, declare a normal array as we have done so far. You can initialize each member using its index and calling the corresponding method. This can be done as follows: using System; delegate double Measure(double R); public class Circle { const double PI = 3.14159; public double Diameter(double Radius) { return Radius * 2; } public double Circumference(double Radius) { return Diameter(Radius) * PI; } public double Area(double Radius) { return Radius * Radius * PI; } } public static class Program { static int Main(string[] args) { double R = 12.55; Circle circ = new Circle(); Measure[] Calc = new Measure[3]; Calc[0] = new Measure(circ.Diameter); double D = Calc[0](R); Calc[1] = new Measure(circ.Circumference); double C = Calc[1](R); Calc[2] = new Measure(circ.Area); double A = Calc[2](R); Console.WriteLine("Circle Characteristics"); Console.WriteLine("Diameter: {0}", D); Console.WriteLine("Circumference: {0}", C); Console.WriteLine("Area: {0}\n", A); return 0; } } You can also list the members of the array when creating it. After creating the array, you can retrieve its value and store it in a variable. Here is an example: public static class Program { static void int(string[] args) { double R = 12.55; Circle circ = new Circle(); Measure[] Calc = new Measure[] { new Measure(circ.Diameter), new Measure(circ.Circumference), new Measure(circ.Area) }; double D = Calc[0](R); double C = Calc[1](R); double A = Calc[2](R); Console.WriteLine("Circle Characteristics"); Console.WriteLine("Diameter: {0}", D); Console.WriteLine("Circumference: {0}", C); Console.WriteLine("Area: {0}\n", A); return 0; } } The above code could also be written as follows: public static class Program { static int Main(string[] args) { double R = 12.55; Circle circ = new Circle(); Measure[] Calc = new Measure[] { new Measure(circ.Diameter), new Measure(circ.Circumference), new Measure(circ.Area) }; Console.WriteLine("Circle Characteristics"); Console.WriteLine("Diameter: {0}", Calc[0](R)); Console.WriteLine("Circumference: {0}", Calc[1](R)); Console.WriteLine("Area: {0}\n", Calc[2](R)); return 0; } } This would produce: Circle Characteristics Diameter: 25.1 Circumference: 78.8539 Area: 494.808
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||