Sequence of execution in multicast delegates in c#
Asked Answered
A

3

8

I read that

If you are using multicast delegates, you should be aware that the order in which methods chained to the same delegate will be called is formally undefined. You should, therefore, avoid writing code that relies on such methods being called in any particular order.

But when I experimented using this code

using System;
namespace Wrox.ProCSharp.Delegates
{
    class Program
    {
        static void One()
        {
            Console.WriteLine("watch when i occur");
            throw new Exception("Error in watching");
        }
        static void Two()
        {
            Console.WriteLine("count");
        }
        static void Three()
        {
            Console.WriteLine("great");
        }
        static void Main()
        {
            Action d1 = Two;
            d1+=Two;
            d1+=Two;
            d1+=Two;
            d1+=One;
            d1+=Three;
            d1+=Three;
            d1+=Three;

            Delegate[] delegates = d1.GetInvocationList();
            foreach (Action d in delegates)
                try
                {
                    d1();
                }
                catch(Exception)
                {
                    Console.WriteLine("Exception Caught");

                }
        }
    }
}

this is the output I got

count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught

Clearly the delegate is executing in the very specified order I wrote it in, and none of the Three() methods executes before the One() method which throws exception.

So is there something I am missing or actually methods in delegates executes in specified order and what I read from the book meant something else.

Angeles answered 30/6, 2014 at 7:14 Comment(1)
Where did you find that quoted text? The official documentation seems to say that the order is indeed defined: learn.microsoft.com/en-us/dotnet/api/system.multicastdelegate The example there demonstrates ordering. Also, learn.microsoft.com/en-us/dotnet/api/system.delegate.combine specifically says that it "concatenates the invocation lists of a and b in that order".Blunderbuss
S
13

undefined - behavior is specified to be arbitrary (like what happens after you forget your wife's birthday...) so depending on arbitrary behaviour is potentially dangerous.

It could be that 5 years from now, Microsoft releases .NET 7 and your program's result changes. That is "undefined" meaning, no amount of measuring today will give you any comfort for the next release, or even between your computer and Fred's computer. So observing it is only interesting, but not useful for reliability. And relying on what you observed is technically wrong.

Sometimes a vendor will specifically document something as undefined to leave themselves flexibility in the implementation.

Scevo answered 30/6, 2014 at 7:19 Comment(6)
Well, book had one programing example on this section and the output I got is very different from the one in book. thnxAngeles
That is another aspect and further evidence of "undefined".Scevo
Do you have any authoritative source? I just stumbled into docs and it seems the order is now defined.Sapsago
@Sapsago - its entirely possible that since my answer, the .NET CLR changed to guarantee the order of execution. It's been 4-5 years, so this was probably as of .NET 4.5.1 or so. Actually its pretty funny and ironic that 5 years ago I said in the answer "could be 5 years from now, Microsoft releases .NET 7 and your program's result changes"Scevo
@codenheim true. I just wanted to make sure I don't miss something. ;)Sapsago
@Sapsago - also possible the original premise of question was wrong - I don't recall if I confirmed the doc excerpt, I think I just answered to the definition of "undefined" but it still gave me a laugh looking back in time and seeing myself write "in 5 years, .NET7 ..."Scevo
H
3

"Formally undefined" simply means: whatever happens is an implementation detail; it might work the way you would naturally expect; it might work completely different, and either is entirely valid. There is no demand mande on implementors that it behaves in any particular order. Further, this might change between framework versions, targets, and implementations.

Basically: even if it does what you expect and want: don't rely on it continuing to do so.

Halibut answered 30/6, 2014 at 7:16 Comment(0)
E
0

I am not an advanced programmer, but after taking a look at your code, I could find some errors.

You need to be using this

Delegate[] delegates = d1.GetInvocationList();
            foreach (Action d in delegates)
            {
                try
                {
                    d();
                }
                catch(Exception e)
                {
                    Console.WriteLine("Exception Caught : "+e.Message);

                }
             }

Instead of this

Delegate[] delegates = d1.GetInvocationList();
            foreach (Action d in delegates)
                try
                {
                    d1();
                }
                catch(Exception)
                {
                    Console.WriteLine("Exception Caught");

                }

And that's what I got

count
count
count
count
watch when i occur
Exception Caught : Error in watching
great
great
great

It is clear that delegates in the invocation list are executed in order

Best regards

Evaporimeter answered 30/11, 2019 at 19:43 Comment(4)
I don't mean to be too harsh, but this is certainly something that should be a comment in the question as it is not answering anything about what was asked (yeah, I know that at the moment you don't have sufficient points, that happens with everybody). This was a 5 years old question and, in my opinion, the code that he used was clearly just something to test the delegate chaining concept, not production code anyway.Ruttger
If you want to test a documented things, at least try to write a correct code. The code that was used is wrong, and Docs are clear "the delegates in the invocation list are called synchronously in the order in which they appear. If an error occurs during execution of the list then an exception is thrown."Evaporimeter
The code is not well-formatted but is not wrong, there is a big difference between the two... There is no compilation or syntax error in the code. As @PedroLorentz said, it is just a test code and does not really need to adhere to the standard coding practices... I would recommend you spend some time thinking about what he said and try to understand it.Angeles
@Madon, on the other hand, your comment here about the docs being clear about the expected behaviour: that would be a great answer if you could copy the part of the official docs that says that and include a link to the page where someone can read more if needed.Ruttger

© 2022 - 2024 — McMap. All rights reserved.