#1,021 – What Happens to a Delegate’s Return Value

The return value from a delegate instance is passed back to the caller.  For example:

        private delegate int ReturnIntDelegate();

        static int Method1()
        {
            return 12;
        }

        static void Main(string[] args)
        {
            ReturnIntDelegate del1 = Method1;

            // Invoke
            int val = del1();
            Console.WriteLine(val);
        }

1021-001

Recall, however, that a delegate instance can refer to more than one method.  When a caller invokes a delegate whose invocation list contains more than one method, the value returned to the caller is the return value of the last delegate instance in the invocation list.  Return values of other methods in the invocation list are lost.

        static int Method1()
        {
            return 12;
        }

        static int Method2()
        {
            return 99;
        }

        static void Main(string[] args)
        {
            ReturnIntDelegate del1 = Method1;
            del1 += Method2;

            // Invoke
            int val = del1();
            Console.WriteLine(val);
        }

1021-002

Advertisements

#377 – Ensure that All of a Delegate’s Methods Are Called by Using GetInvocationList

When an exception occurs during the invocation of one of the methods a delegate refers to, the delegate does not continue invoking methods in its invocation list.

To ensure that all methods in the delegate’s invocation list are called, even when exceptions occur, you can call GetInvocationList and invoke the methods directly, rather than letting the delegate invoke them.

        private delegate void StringHandlerDelegate(string s);

        static void Main()
        {
            // Add two methods to delegate instance
            StringHandlerDelegate del = Method1;
            del += Method2;

            // Invoke
            foreach (StringHandlerDelegate nextDel in del.GetInvocationList())
            {
                try
                {
                    nextDel.Invoke("Yooper");
                }
                catch (Exception xx)
                {
                    Console.WriteLine(string.Format("Exception in {0}: {1}", nextDel.Method.Name, xx.Message));
                }
            }
        }

        static void Method1(string text)
        {
            Console.WriteLine("Method1, {0}", text);
            throw new Exception("Problem in Method1");
        }

        static void Method2(string name)
        {
            Console.WriteLine("Method2, {0}", name);
        }

When you execute the code, you’ll see that Method2 is called, even though Method1 throws an exception.

#376 – What Happens When an Exception Occurs During Delegate Invocation

When you invoke a delegate, it will call each of the methods in its invocation list, one at a time.  If an exception is thrown from within one of those methods, the delegate will stop invoking methods in its invocation list and throw an exception up to the caller that initiated the invocation.  Methods on the invocation list that haven’t already been called will not get called.

In the example below, the delegate’s invocation list has two methods–Method1 and Method2Method1 raises an exception and Method2 is never called.

        private delegate void StringHandlerDelegate(string s);

        static void Main()
        {
            try
            {
                // Add two methods to delegate instance
                StringHandlerDelegate del = Method1;
                del += Method2;

                // Invoke
                del("Yooper");
            }
            catch (Exception xx)
            {
                Console.WriteLine("Exception: {0}", xx.Message);
            }
        }

        static void Method1(string text)
        {
            Console.WriteLine("Method1, {0}", text);
            throw new Exception("Problem in Method1");
        }

        static void Method2(string name)
        {
            Console.WriteLine("Method2, {0}", name);
        }