Delegation, Lambda expressions, event series 04, how the delegation chain is formed, multicast delegation, calling the delegation chain method, delegation chain Exception Handling, lambda expressions

Source: Internet
Author: User

Delegation, Lambda expressions, event series 04, how the delegation chain is formed, multicast delegation, calling the delegation chain method, delegation chain Exception Handling, lambda expressions

The delegate is multicast delegate. We can assign multiple methods to the delegate variable through "+ =", thus forming a delegate chain. This topic includes how the delegated link is formed, how to call the delegated link method, and how to handle exceptions of the delegated link.

 

□Call the delegate chain method formed by the delegate whose return type is void
□Call the delegate chain method formed by the delegate of the return type not void
□Call the delegate chain method formed by a wildcard Delegate of the return type not void
□Call the delegation chain method formed by the generic delegation of Func <T>
□Call the delegate chain method formed by the Action <T> generic delegate
□Handling delegate link exceptions

 

Call the delegate chain method formed by the delegate whose return type is void

Let's look at the following example:

namespace ConsoleApplication3
{
    internal delegate void MySayDel(string msg);
    class Program
    {
        static void Main(string[] args)
        {
            MySayDel del = SayHello;
Del = (MySayDel) Delegate. Combine (del, new MySayDel (SayNice); // equivalent to: del + = SayNice;
            del += SayOk;
            del("darren");
        }
        static void SayHello(string msg)
        {
            Console.WriteLine("hello " + msg);
        }
        static void SayNice(string msg)
        {
            Console.WriteLine("nice " + msg);
        }
        static void SayOk(string msg)
        {
            Console.WriteLine("ok " + msg);
        }
    }
}


Finally, call the delegate execution method. The first registered method is executed first. "+ =" Is a type of "syntactic sugar". In fact, the static Combine method of Delegate is called internally to form a Delegate chain, and then the Delegate chain is assigned to the Delegate variable. It is roughly as follows:

→ When MySayDel = SayHello is executed;

→ When del = (MySayDel) Delegate is executed. combine (del, new MySayDel (SayNice), creates a MySayDel delegate instance on the hosting stack to point to the SayNice method, and then copies the original delegate instance pointing to the SayHello method, two delegated instances form a delegated chain, that is, the blue area. The delegated variable del on the stack points to the delegated chain.

 

Call the delegate chain method formed by a delegate whose return type is not void

In the preceding example, the return type of the delegate is void. When the delegate is called, the delegate chain method is executed in sequence. However, if the return type of the delegate is not void, will the delegate chain methods be executed in sequence?

    internal delegate int MyCalulateDel(int val1, int val2);
    class Program
    {
        static void Main(string[] args)
        {
            MyCalulateDel del = Add;
            del += Sub;
            Console.WriteLine(del.Invoke(20, 10));
        }
        static int Add(int val1, int val2)
        {
            return val1 + val2;
        }
        static int Sub(int val1, int val2)
        {
            return val1 - val2;
        }
    }


In the preceding example, when the delegate is called, the delegate chain method is not executed in sequence, but the last registered method is executed.

 

What should we do if we want to get the results returned by all delegate methods?
-- The delegate provides an instance method of GetInvocationList for us to obtain all the delegates.

    internal delegate int MyCalulateDel(int val1, int val2);
    class Program
    {
        static void Main(string[] args)
        {
            MyCalulateDel del = Add;
            del += Sub;
            var result = GetResultForEachDel(del, 20, 10);
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }
        }
        static List<int> GetResultForEachDel(MyCalulateDel del, int val1, int val2)
        {
            List<int> result = new List<int>();
            foreach (MyCalulateDel item in del.GetInvocationList())
            {
                result.Add(item.Invoke(val1, val2));
            }
            return result;
        }
        static int Add(int val1, int val2)
        {
            return val1 + val2;
        }
        static int Sub(int val1, int val2)
        {
            return val1 - val2;
        }
    }


The above Code uses the GetInvocationList instance method to retrieve all delegates and then call all the delegate methods respectively.

 

Call the delegate chain method formed by a wildcard Delegate of the return type not void

The preceding delegation only applies to the int type. If you do not want to overwrite the type, you should use the generic delegation.

namespace ConsoleApplication5
{
    internal delegate T MyGenericDel<T>();
    class Program
    {
        static void Main(string[] args)
        {
            MyGenericDel<int> d = ReturnOne;
            d += ReturnTwo;
            var result = GetReturnValues(d);
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }
        }
// Execute all generic delegation
        static IEnumerable<TModel> GetReturnValues<TModel>(MyGenericDel<TModel> d) 
        {
// Traverse the delegate chain
            foreach (MyGenericDel<TModel> del in d.GetInvocationList())
            {
                yield return del.Invoke();
            }
        }
        static int ReturnOne()
        {
            return 1;
        }
        static int ReturnTwo()
        {
            return 2;
        }
    }
}

Generic delegation. Generally, a placeholder <T> is added after the return type name, method name, and parameter type name.

 

Call the delegate chain method formed by the wildcard delegation of Func <T>

In fact, for generic delegation,. NET has prepared Func <T> for us. It has multiple overload methods:


The last parameter is the return type, and the other parameters are the input parameters.

    class Program
    {
        static void Main(string[] args)
        {
            Func<int> d = ReturnOne;
            d += ReturnTwo;
            var result = GetReturnValues(d);
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }
        }
// Execute all generic delegation
        static IEnumerable<TModel> GetReturnValues<TModel>(Func<TModel> d) 
        {
// Traverse the delegate chain
            foreach (Func<TModel> del in d.GetInvocationList())
            {
                yield return del();
            }
        }
        static int ReturnOne()
        {
            return 1;
        }
        static int ReturnTwo()
        {
            return 2;
        }
    }


 

Call the delegate chain method formed by Action <T> generic delegation

If a generic delegate does not return a value, you can use Action <T>, which has multiple overload methods:

All parameters are input parameters and no return value is returned.

 

    class Program
    {
        static void Main(string[] args)
        {
            Action<string> action = SayOnce;
            action += SayTwice;
            action.Invoke("darren");
        }
        static void SayOnce(string str)
        {
Console. WriteLine ("I only say once" + str );
        }
        static void SayTwice(string str)
        {
Console. WriteLine ("My first time said" + str );
Console. WriteLine ("the second time I said" + str );
        }
    }

 

Handling delegate link exceptions

In the delegate chain, if any delegate method throws an exception, how can this problem be solved?
-- You need to traverse the delegate chain so that each delegate can be executed separately and write the exception handling code.

    class Program
    {
        static void Main(string[] args)
        {
            Action<string> action = SayOnce;
            action += SayTwice;
            foreach (Action<string> a in action.GetInvocationList())
            {
                try
                {
                    a("darren");
                }
                catch (Exception)
                {
Console. WriteLine ("exception occurred ");
                }
            }
        }
        static void SayOnce(string str)
        {
Console. WriteLine ("I only say once" + str );
        }
        static void SayTwice(string str)
        {
Console. WriteLine ("My first time said" + str );
Console. WriteLine ("the second time I said" + str );
            throw new Exception();
        }
    }


Summary:
○ If the return type of the delegate is void and the delegate chain is formed, the delegate chain method will be executed in sequence as long as the delegate is called.
○ If the return type of the delegate is not void and the delegate chain is formed, you can use the delegate's GetInvocationList instance method to obtain all the delegates, and then traverse these delegates to execute the delegate method in sequence to obtain the return type.
○ For generic delegation, Func <T> and Action <T> are preferred. If there is a return type, Func <T> is used. If the return type is void, Action <T> is used.
○ The idea of handling exceptions in the delegate chain is to traverse each delegate in the delegate chain and write the code to capture exceptions for each delegate.

 

 

"Delegation, Lambda expressions, and event series" include:

Delegate, Lambda expression, event series 01, Delegate, basic delegate usage, delegate Method and Target attribute delegate, Lambda expression, event series 02, when should I use delegate, Lambda expression, event series 03, from delegate to Lamda expression?

Delegation, Lambda expressions, event series 04, how the delegation chain is formed, multicast delegation, calling the delegation chain method, delegation chain Exception Handling delegation, Lambda expressions, event series 05, action delegate and closure delegate, Lambda expression, and event series 06. Use Action to implement observer mode and experience the differences between delegate and event
How to Use lambda in C # To handle delegate events

The delegate is defined as follows: copy the code as follows: public class SocketSp {public delegate void ReceiveCompleted (byte [] receiveBuffer, int etetotallen, Exception ex); public ReceiveCompleted receiveCompleted ;} the following copy code is defined by the Caller: public class LinkOuter {SocketSp linkOuterSocket = new SocketSp (); private void test (Socket requestHandleSocket) {// link linkOuterSocket here. receiveCompleted event. You also want to pass in the requestHandleSocket parameter for later processing .}} The first idea was to use delegate but failed. Although it is attached, the parameter passed by the delegate is lost and subsequent operations cannot be performed. Copy the Code as follows: private void test (Socket requestHandleSocket) {linkOuterSocket. receiveCompleted + = delegate {// To do};} The second idea is To use Action, and the result also fails. The IDE prompts that the delegated Action does not use three parameters. The copy code is as follows: private void test (Socket requestHandleSocket) {linkOuterSocket. receiveCompleted + = (Action) (outerReceiveBuffer, totalLen, ex) =>{// To do});} The third idea is To use lambda expressions To First connect To the delegate, at the same time, the call of local variables is used to transmit parameters to the sendResponse function for subsequent operations. The copy code is as follows: private void test (Socket requestHandleSocket) {linkOuterSocket. receiveCompleted + = new SocketSp. receiveCompleted (outerReceiveBuffer, totalLen, ex) => {byte [] realOuterReceiveBuffer = new byte [totalLen]; Array. copy (outerReceiveBuffer, 0, realOuterReceiveBuffer, 0, totalLen); sendResponse (requestHandleSocket, realOuterReceiveBuffer, "200 OK", "text/html ");});} finally, it is implemented using lambda expressions. Articles that you may be interested in: C # Use Lambda and delegate template Methods

C # delegation chain problems

Two methods have been attached to your delegate d1. When d1 is called, both methods are actually called.
However, multiple methods have multiple return values, and only one variable is accepted. Therefore, the returned values of the method called later overwrite the returned values of the preceding method. In other words, the previous return values are discarded.

This is why void is used as the return value when event delegation is defined.

[Answer supplement]

You can check whether the Delegate/event provided by the system class library is of the void return type.

If you have to perform a delegate with a returned value, you can do this:
......
Public string CreateDelegate ()
{
Class1 c1 = new Class1 ();
MyDelegate d1 = new MyDelegate (c1.delegateMethod1 );
D1 + = c1.delegateMethod2;
String d = "";
Foreach (MyDelegate x in d1.GetInvocationList ())
{
D + = x ("Hello World ");
}
Return d;
}
......

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.