Introduction to Data Types in c # (delegation ),

Source: Internet
Author: User

Introduction to Data Types in c # (delegation ),
C # Introduction to data types (Delegation) What is delegation?

A delegate is a type that encapsulates a class of methods with the same method signature ). The definition may sound a bit confusing. First, you can determine whether a delegate is a data type. What is a method signature is actually the input parameter list and output parameter type of the method. Let's take a look at the following example. deleMthod defines three methods: add, minus, and multi. They all have the same input parameter list (int x, int y) and output parameter type int, the three methods have the same method signature. Developers can use an abstract type of an int name (int x, int y) to encapsulate the method. In c #, this abstract data type is called a delegate, for the preceding methods, we can define the delegate: public delegate int Handler (int x, int y), public is an access modifier, and the delegate keyword indicates that this is a delegate, int Hander (int x, int y) indicates the name of the delegate.

  class deleMethod    {        public int add(int x, int y)        {            return x + y;        }        public int minus(int x, int y)        {            return x - y;        }        public int multi(int x, int y)        {            return x * y;        }    }
How to Use Delegation

There are four steps to use delegation:

  • Define a delegate as mentioned in the previous section.
  • Define the delegate method. In the last section, add, minus, and multi in the deleMethod class are all delegate methods. The purpose of the definition is to use it. The professional point is to call the method.
  • Delegate variable and assign value, same as the type, need to assign value to the variable before use.
  • Use of delegate variables.

How to define the delegate variable? Let's continue with the example above. We have defined a delegate Type public delegate int Handler (int x, int y). Like the c # syntax, the syntax for defining a variable and assigning values is: "Type name variable name = new type name (method);", as shown in the preceding example

"Handler deleCall = new Handler (method name);" after. net2.0, the delegation instantiation can be simplified to "Handler deleCall = method name;".

The use of delegate variables is the call to delegate methods. The syntax is "int result1 = deleCall (10, 20);" or use the delegate call method Invoke, "int result2 = deleCall. Invoke (10, 20 );".

For more information, see the following example:

Class Program {public delegate int Handler (int x, int y); // --- defines the delegate type, the delegate can be viewed as a Special Data Type static void Main (string [] args) {deleMethod dm = new deleMethod (); // --- instantiate Handler deleCall = new Handler (dm. add); // --- define the delegate variable delCall and present the converted value int result1 = deleCall (10, 20); // --- Call the invoke Console of the instance method. writeLine ("the add resutl is: {0}", result1); deleCall = dm. minus; int result2 = deleCall. invoke (12, 6); Console. writeLine ("the minus result is: {0}", result2); Console. readLine ();}}

As shown in the preceding example, defining a simple addition and subtraction function is so complicated that it is speechless to stir up people's heads. It is no wonder that many friends talk about the Commission and the color changes. In actual use, c # still has many ways to help us simplify the code.

Simplify predefined generic delegation

C # The most common predefined types of delegation are Func <> delegate, Action <> delegate, and Predicate <> delegate. Func <> delegate is a delegate with a returned value, the number of input parameters can be up to 16, while the Action <> delegate is a delegate without return values, and its input parameters can also be up to 16; predicate <> is a delegate with the bool return type. It runs only one input parameter. For the delegate type in the preceding example, we can use the predefined delegate type Fun <int, int, int>, the Code of public delegate int Handler (int x, int y) is simplified as follows:

Namespace DelegateDemo1 {class Program {static void Main (string [] args) {deleMethod dm = new deleMethod (); Func <int, int, int> fun = dm. add; // --- use the predefined delegate type Func <> int result4 = fun (8, 10); Func <int, int, int> fun1 = dm. minus; int result5 = fun1 (12, 8); Console. writeLine ("predefined delegate output {0}, {1}", result4, result5); Console. readLine () ;}} class deleMethod {public int add (int x, int y) {return x + y;} public int minus (int x, int y) {return x-y;} public int multi (int x, int y) {return x * y ;}}}

If I put together the definition of the delegate method and the call of the delegate, is it easier and easier than a previously defined delegate type? However, it is not easy to use delegation in this way. It is estimated that few people will write code in actual applications, which is too inconvenient.

Anonymous Delegation

When the call of the delegated instance is separated from the definition of the delegate method, the coders need to find the delegate method to match the delegate variable when reading the program code, check whether the parameter list and return values are correct. Such program code is poorly readable. In fact, c # still has a way to simplify the code: that is, anonymous delegation. The method body is provided directly during the delegation instantiation, the reason for anonymous delegation is that the name of the delegate is omitted when the delegate is re-defined. Its definition syntax is delegate (parameter 1, parameter 2), and the method body is directly given after it is defined, enclose the method in braces. It just looks weird and gets used to it when it comes to getting started. There is no way to adapt to the c # syntax. It is better to look at the Code directly if it is water.

Namespace DelegateDemo1 {class Program {static void Main (string [] args) {Func <int, int, int> fun = delegate (int x, int y) {return x + y ;}; Func <int, int, int> fun1 = delegate (int x, int y) {return x-y ;}; int result4 = fun (8, 10); int result5 = fun1 (12, 8); Console. writeLine ("predefined delegate output {0}, {1}", result4, result5); Console. readLine ();}}}

Let's see if the code volume is greatly reduced on the basis of the original, and the code volume has been reduced to the limit?

Lambda expressions

In fact, the definition of the delegate can be further simplified, that is, the lambda expression is used. The definition of the lambda expression is (parameter list) =>{ method body}, => read as goes. Lambda expressions streamline the parameter list and method expressions to the extreme. In the preceding example, using lambda expressions can omit the keywords and parameter types of anonymous delegation. The system can perform type inference, the simplified code is as follows. For. net 1.0 and 2.0, the most traditional definition and use of delegation is a huge simplification, which removes all redundant statements to the extreme.

Namespace DelegateDemo1 {class Program {static void Main (string [] args) {Func <int, int, int> fun = (x, y) => x + y; func <int, int, int> fun1 = (x, y) => x-y; int result4 = fun (8, 10); int result5 = fun1 (12, 8); Console. writeLine ("predefined delegate output {0}, {1}", result4, result5); Console. readLine ();}}}
Delegated chain

As mentioned above, the delegate is essentially a class. All the delegates declared using the delegate keyword inherit from System. MulticastDelegate. The latter is inherited from the System. Delegate class, while the System. Delegate class inherits from the System. Object Class. A delegate can bind several methods with the same signature to form a delegate chain, which is a set of delegate instances, it allows us to call all the methods represented by the delegate instance in this set (for methods with return values, the return value of the delegate chain is the return value of the last method in the linked list ), in the following example, the principal method we define does not return values. We can use the GetInvocationList () method to obtain the delegate chain.

Class Program {static void Main (string [] args) {// Action indicates a type of Action <int, int> actionA = (x, y) =>{ Console. writeLine ("x is {0}, y is {1}, and their sum of squares is {2}", x, y, x * x + y * y );}; actionA + = (x, y) => {Console. writeLine ("x is {0}, y is {1}, their squared difference is {2}", x, y, x * x-y * y );}; actionA (10, 5 );

Foreach (var item in actionA. GetInvocationList ())
Console. WriteLine (item. Method );

            Console.ReadLine();        }    }
What is an event?

It is often seen that an event is a Special Delegate and is an encapsulation of the delegate. In fact, this definition is not rigorous. A delegate is a data type, but an event is only a delegated instance and cannot be regarded as a data type. Therefore, it is inaccurate to say that an event is a special delegate. If it is defined as follows: an event is a special delegate instance and is an encapsulation of the delegate. How are events defined and used in C? In fact, events take four stages from definition to use.

  • Define the delegate on which the event depends, and define the event and the method for triggering the event. This step can be defined in the event publisher class.
  • Define the event method that the event depends on. This step can be defined in the event subscriber class.
  • If there are event parameters, this step can be defined in the event parameter class
  • Register and trigger events. This step is generally written in the main program.

Generally, there are no Uniform Naming standards for each method in the event definition process, but we can refer to Microsoft's naming rules in c # for naming.

We recommend that you name the event Delegate as event + EventHandler. If there is additional parameter transfer, you need to define your own parameter type. The parameter type naming convention: event + EventHandler. For example, you can define an event delegate public delegate void calcEventHandler (object sender, calcEventArgs e );.

Define an event variable such as: public event calcEventHandler calc;

Define a method for triggering an event, such as public void onCalc (object sender, calcEventArgs e ){}

It is recommended that the method name be on + event, just as when we develop a web program, the bound event names include onClick and onLoad.

Refer to the example below to understand the general process of defining an event. If you do not need to pass event parameters, you can save the definition of the event parameter class and use the EventArgs predefined by the system.

/// <Summary> /// Main Program class /// </summary> class Program {static void Main (string [] args) {eventPublish myEvent = new eventPublish (); eventsubpipeline myMethod = new eventsubpipeline (); // The binding method add and subtract, also known as event method registration-= is called the cancellation of myEvent on the event method. calc ++ = myMethod. add; myEvent. calc ++ = myMethod. substract; while (true) {try {Console. writeLine ("Enter the first integer number"); int numA = Convert. toInt16 (Console. readLine (); Co Nsole. writeLine ("enter the second integer"); int numB = Convert. toInt16 (Console. readLine (); calcEventArgs e = new calcEventArgs (numA, numB); // In this example, the sender parameter is not required and the string "sender" myEvent is randomly transmitted. onCalc ("sender", e);} catch (Exception ex) {Console. writeLine ("error," + ex. message) ;}}}/// <summary> // defines an event publisher class // </summary> class eventPublish {// defines a delegate type, the delegate name is generally the event variable name + EventHandler public delegate void calcEventHande R (object sender, calcEventArgs e); // defines an event variable named calc public event calcEventHander calc; // encapsulates the event and defines the method for triggering the event, the defined trigger method name is generally the on + Event variable name public void onCalc (object sender, calcEventArgs e) {if (calc! = Null) calc (sender, e) ;}/// <summary> // defines an event subscriber class (event method class) /// </summary> class eventsubtasks {public void add (object sender, calcEventArgs e) {Console. writeLine ("the sum of two numbers equals {0}", e. X + e. y);} public void substract (object sender, calcEventArgs e) {Console. writeLine ("Two subtraction equals {0}", e. x-e. y) ;}/// <summary> // defines an event parameter class /// </summary> class calcEventArgs: EventArgs {private int _ x; private int _ y; public calcEventArgs (int x, int y) {this. _ x = x; this. _ y = y;} public int X {get {return _ x;} public int Y {get {return _ y ;}}}

We encapsulate the event as a delegate. If we use ILDAS to decompile the executable file and view the intermediate code, we can clearly see the event running mechanism.

As shown in, the event calc goes through. when the net Runtime is compiled into an intermediate language, a private calc attribute is generated, and the add_calc and remove_calc methods are automatically generated for registering and deregistering subscriber methods. Because the event is encapsulated, although the calc attribute is private, you can directly call it in the publisher class using methods such as calc (sender, e; however, in the main program, if this method is used, an error occurs. The onCalc method can only be used for indirect calls.

Postscript

In this article, I first raised the question of what is delegation, and introduced several methods to illustrate what delegation is to enhance my understanding of the concept of delegation. The second part describes the four steps for using delegation, and describes these steps through examples. The third part describes how to simplify delegation. You can use generic delegation to simplify custom delegation and use anonymous delegation to simplify the definition of delegation methods. The anonymous delegate directly gives the method body when defining the delegate, and further simplifies the use of the delegate by using the lambda expression type inference. The fourth part describes the delegate chain, initialize the delegate through the binding method, and bind more delegate methods through + =. The fifth part describes the four steps of event definition and use. Of course, there are many other scenarios for delegation. For example, asynchronous calling through BeginInvoke and EndInvoke is not the focus of this article, so it is not mentioned in this article.

 

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.