C # delegation,

Source: Internet
Author: User

C # delegation,

If you want to pass a method parameter to a method, you can use the delegate. To pass a method, you must encapsulate the details of the method in a new type of object within one minute, that is, delegate. A delegate is a special type of object. Its special feature is that all objects we previously defined contain data, and the delegate only contains the addresses of one or more methods.
In. NET, the delegate points to the method address. In C ++, the function pointer is a pointer to the memory location, but it is not type-safe. Developers cannot determine what the pointer actually points to, and do not even know the parameters and return values.
. NET delegate is a type-safe class that defines the types of return types and parameters. The delegate class not only contains references to methods, but also can contain references to multiple methods.
1. Declare Delegation
The use of delegation is the same as the use of classes, and two steps are also required to be defined and instantiated. First, you must define the delegate to be used. For the delegate, defining it is to tell the Compiler which type of delegate represents this type of method. Then, you must create one or more instances of the delegate to use it. The compiler creates a class that indicates the delegate in the background.
Syntax for defining delegation:
Delegate void IntMethod (int x); // defines a delegate IntMethod, specifying that each instance of the delegate can contain reference of one or more methods, the referenced method must contain an int parameter and return void.

Because the definition delegate basically defines a new class, the delegate can be defined anywhere in the definition class. You can also use the modifiers public, private, and protected on the definition of the delegate.
The Delegate is derived from the base class System. MulticastDelegate, and MulticastDelegate is also derived from the base class System. Delegate.
The class has two different terms: "class" indicates a broad definition, "object" indicates, and the class instance. However, there is only one term for delegation. When you create a delegated instance, the created instance is still called a delegated instance. The specific meaning of the delegate must be determined from the context.

2. Use Delegation
After the delegate is defined, you can create an instance of it to store the details of a specific method.

                delegate void IntMethod(int x);        static void Fun(int x)        {            Console.WriteLine(x);        }        static void Main()        {          int x = 40;          IntMethod intMethod = new IntMethod(Fun);          intMethod(x);          Console.ReadKey();        }

The delegate syntax always accepts a parameter constructor. this parameter is the delegate reference method. This method must match the signature when the delegate is initially defined.
Use the name of the delegated instance, followed by parentheses. If you need a parameter, you must add the parameter in parentheses.
The parentheses provided to the delegated instance are identical to the Invoke () method used to call the delegate class:
IntMethod (x );
IntMethod. Invoke (x );

To reduce the input, you only need to pass the method address name to the delegate instance. This is called deleGATE inference.
IntMethod intMethod = new IntMethod (Fun );
IntMethod intMethod = Fun;
Delegation inference can be used anywhere in the instance to be delegated. Delegation inference can also be used for events because the events are based on delegation. (The event will be introduced in later articles)

Note: You can use a delegate to call methods of any type of object, whether it is a static method or an instance method.

3. Use a delegate Array

  

// Define two methods in a class: class MathOperations {public static double MultiplyByTwo (double value) {return value * 2;} public static double Square (double value) {return value * value ;}}
// Define a delegate double DoubleOp (double x) with double type parameters returned; class Program {static void Main () {// instantiate the delegate array, same as the array of the instantiation class, DoubleOp [] operations = {MathOperations. multiplyByTwo, MathOperations. square}; // traverses the array and uses each delegate instance in the array for (int I = 0; I <operations. length; I ++) {Console. writeLine ("Using operations [{0}]:", I); // pass the delegated instance as a parameter to the ProcessAndDisplayNumber method ProcessAndDisplayNumber (operations [I], 2.0 ); processAndDisplayNumber (operations [I], 7.94); ProcessAndDisplayNumber (operations [I], 1.414); Console. writeLine () ;}} static void ProcessAndDisplayNumber (DoubleOp action, double value) {// call the delegate in ProcessAndDisplayNumber and execute the double result = action (value) method referenced by the delegate instance ); console. writeLine ("Value is {0}, result of operation is {1}", value, result );}}

 

4. Action <T> and Func <T> delegate
In addition to defining a delegate type for each parameter and return type, you can also use the Action <T> and Func <T> delegate.
The generic Action <T> delegate refers to a void return type method. This delegate class has different variants and can pass up to 16 different parameter types. Action classes without generic parameters call methods without parameters. Action <in T> calls a method with one parameter. Action <in T1, in T2> calls a method with two parameters, and so on.
Func <T> delegate allows calling methods with return types. Similar to Action <T>, Func <T> also has different variants. up to 16 different parameter types and one return type can be passed. Func <out TResult> the delegate type can call methods without parameters and with return types.

The following uses Func <T> delegate to implement a function that is hard to write without delegation: sort the object array. if the object is an int or string value type object, it will be easy to sort, if you want to sort objects of many custom types, you need to write a lot of code. Using delegation reduces the amount of code.
Define classes that contain comparison methods:
The BubbleSorter class implements a generic method Sort <T>. The first parameter is the array of objects to be sorted, and the second parameter is a delegate that transmits methods to compare two objects. In this way, you can pass the custom comparison method to the Sort <T> method.

  

Class BubbleSorter {static public void Sort <T> (IList <T> sortArray, Func <T, T, bool> comparison) {bool swapped = true; do {swapped = false; for (int I = 0; I <sortArray. count-1; I ++) {// call the method referenced in the delegate and compare the two objects if (comparison (sortArray [I + 1], sortArray [I]) {T temp = sortArray [I]; sortArray [I] = sortArray [I + 1]; sortArray [I + 1] = temp; swapped = true ;}}} while (swapped );}}

 

Define a custom class

      class Employee          {            public Employee(string name, decimal salary)            {              this.Name = name;              this.Salary = salary;            }            public string Name { get; private set; }            public decimal Salary { get; private set; }            public override string ToString()            {              return string.Format("{0}, {1:C}", Name, Salary);            }            public static bool CompareSalary(Employee e1, Employee e2)            {              return e1.Salary < e2.Salary;            }          }

Client code:

  

Employee [] employees = {new Employee ("Bugs Bunny", 20000), new Employee ("Elmer Fudd", 10000), new Employee ("Daffy Duck", 25000 ), new Employee ("Wile Coyote", 1000000.38 m), new Employee ("Foghorn Leghorn", 23000), new Employee ("RoadRunner", 50000 )}; // Sort executes the custom Employee. compareSalary method BubbleSorter. sort (employees, Employee. compareSalary); foreach (var employee in employees) {Console. writeLine (employee );}

 

 

5. multicast Delegation
Each delegate described above contains only one method call, and the delegate can also contain multiple methods. This type of delegation is called multicast delegation.
If you call multicast delegates, you can call multiple methods in sequence. However, if the delegate signature does not return the void, you can only get the result of the last method called by the delegate.
Use + = to add a method and-= to delete a method.

  

    static void Main()        {          Action<double> operations = MathOperations.MultiplyByTwo;          operations += MathOperations.Square;          ProcessAndDisplayNumber(operations, 2.0);          ProcessAndDisplayNumber(operations, 7.0);          Console.WriteLine();        }        static void ProcessAndDisplayNumber(Action<double> action, double value)        {          Console.WriteLine();          Console.WriteLine("ProcessAndDisplayNumber called with value = {0}", value);          action(value);        }                class MathOperations          {            public static void MultiplyByTwo(double value)            {              double result = value * 2;              Console.WriteLine("Multiplying by 2: {0} gives {1}", value, result);            }            public static void Square(double value)            {              double result = value * value;              Console.WriteLine("Squaring: {0} gives {1}", value, result);            }          }

Each time the ProcessAndDisplayNumber method is called, two methods in the action delegate instance are called in sequence.
Output:
ProcessAndDisplayNumber called with value = 2
Multiplying by 2: 2 gives 4
Squaring: 2 gives 4

ProcessAndDisplayNumber called with value = 7
Multiplying by 2: 7 gives 14
Squaring: 7 gives 49

The delegate can also use the +,-OPERATOR:
Action <double> operations1 = MathOperations. MultiplyByTwo;
Action <double> operations2 = MathOperations. Square;
Action <double> operations = operations1 + operations2;
Operations = operations-operations2;


Multicast delegates include a set of delegates called one by one. If one of the methods throws an exception, the entire iteration stops.
Static void One ()
{
Console. WriteLine ("One ");
Throw new Exception ("Error in one ");
}

Static void Two ()
{
Console. WriteLine ("Two ");
}


Static void Main ()
{
Action d1 = One;
D1 + = Two;

Try
{
D1 ();
}
Catch (Exception)
{
Console. WriteLine ("Exception caught ");
}


}
The delegate only calls the first method. Because the first method throws an exception, the iteration of the delegate stops and the Two () method is no longer called.

To avoid this problem, you can use the GetInvocationList () method defined by the Delegate class to return an array of Delegate objects:
Action d1 = One;
D1 + = Two;

Delegate [] delegates = d1.GetInvocationList ();
Foreach (Action d in delegates)
{
Try
{
D ();
}
Catch (Exception)
{
Console. WriteLine ("Exception caught ");
}
}

Output:
One
Exception caught
Two

Using the GetInvocationList () method, you can pass different parameters for each delegate method to obtain the return values of each method.
Static int One (int x)
{
Return x;
}

Static int Two (int x)
{
Return x;
}


Static void Main ()
{

Func <int, int> d1 = One;
D1 + = Two;

Delegate [] delegates = d1.GetInvocationList ();
Func <int, int> d2 = (Func <int, int>) delegates [0];
Console. WriteLine (d2 (1 ));

Func <int, int> d3 = (Func <int, int>) delegates [1];
Console. WriteLine (d3 (2 ));

Console. ReadKey ();
}
Output:
1
2

6. Anonymous Method
The anonymous method can be used to directly assign the method body to the delegated instance without defining a method.
Static void Main ()
{
String mid = ", middle part ,";

Func <string, string> anonDel = delegate (string param)
{
Param + = mid;
Param + = "and this was added to the string .";
Return param;
};
Console. WriteLine (anonDel ("Start of string "));

}
The above code is not to assign the method name to the delegate variable anonDel, but a piece of code, which is preceded by the keyword delegate and parameter list. You can use external variables when using anonymous methods.
The advantage of the anonymous method is that it reduces the amount of code. Using the anonymous method does not speed up code execution. The compiler still defines a method with only one automatically specified name.

To use the anonymous method, you must follow two rules:
(1). You cannot use the jump Statement (break, goto, AND continue) in the anonymous method to be transferred to the external method, and the external Code cannot be transferred to the Internal method of the anonymous method.
(2) The anonymous method cannot access Insecure code. You cannot use ref or out in anonymous methods.

If you need anonymous methods to write the same function multiple times, do not use anonymous methods.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.