Riddle me this...
What is the result of this piece of code?
application.Startup += delegate { Console.WriteLine("will it"); application.Startup += delegate { Console.WriteLine("work?"); }; };
As usual, I am raffling a Rhino Mocks license among those who will answer correctly.
Comments
Heh. I'm going to guess that you will get all of it. I'm guessing that even though the second delegate is wired up during the event, it will execute it after it finishes the first? Hmm. I change my mind. I bet you can't add delegates to an event while your in the event. Do you get an exception? Do I lose my Rhino Mocks lic if I get it wrong? ;)
I'd think that you should be able to wire up a delegate to an event anywhere. So, both delegates should be wired in this case but the order of calling them is undefined. So, um..the second one may or may not get called. Am I back to square one ?
probably just get "will it". It's like registering for an event after the event was called.
Is it thread safe to add/remoe events? hm...
I'm thinking just the "will it" part. The startup event will probably only fire once, which will execute the first delegate code. This will attach more code to the event, but unless Startup fires again you wouldn't get anything.
If it went twice you'd probably get
will it
will it work?
I'd assume the inner event hookup will fire because it will be placed at the end of the stack and fired when the outer event hookup is complete.
I'd say that one should be able to wire up delegates anywhere, including inside a delegate.
That being said, IIRC, the handler for delegates first gets the list of all that is wired up, and executes them. And that would mean that wiring up another delegate would not make it execute until next time.
Then again, maybe the compiler treats that as an error and doesn't allow wiring up delegates in side delegates at all. Too lazy to check :p. But I still stand by my first paragraph.
I'm with josh. If he is correct, will it mean that we will have to share the rhino mocks license? :-)
Yes it will work but you will never see the second code being executed since the event only fires once. (Same as Dave)
The result of THAT piece of code is that you'll have a handler wired up to the Startup event/delegate. :P
Well, invoking events should be inherently thread-safe, and that must mean that the invoker does something akin to cloning the list of handlers, then calling each of them in some undefined order.
Hence, the second wiring will take effect during the first invocation, but will only fire if Startup is invoked again. So I'm betting my rhino mocks license on "Will it" alone.
I don't know how event handlers are invoked by the runtime, but if it's something like a foreach loop, then you may get an error for trying to change the Enumerabe during the enumeration.
You hooked up a delegate which will in turn add another delegate to the invocation list (possibly failing, depending on the implementation), but which will never invoke since the application has already started? :-)
In case the first time the Startup event is fired "will it" will be displayed.
The second time it will display
will it
work?
The third time
will it
work?
work?
On so on...
I guess it should work as follows:
every time event is fired it gets the list of delegates to invoke and start calling it one by one...
in case we add one more delegate to invocation list from one of delegates called on step 1, everything is Ok, except that it won't be called right away as we have received our local copy of delegate list to invoke on the step 1.
I guess it will only print "will it".
Whats 'application'? And hasn't the Application.Startup event already fired by the time your code runs?
Areil,
Application is a WPF app.
The question is about events, not about the specific case.
It will print only "will it".
When two delegates are combined, a new delegate results with its own invocation list. The invocation list of the first delegate (which is coincidently in the midst of being invoked) is unchanged.
In other words, invocation lists are immutable. The += operator creates a new invocation list behind the scenes.
That's good to know. But it effectively means the same thing as the "get a copy of the handlers list and call that" guess (at least in this scenario).
Although the question may be about events in general, it will entirely depend on the specifics of what's raising the event.
If it's coded in the "normal" manner, it will only show "will it" for the immutability reasons listed before. However, you could fairly easily code the event (or the firing code) to do something different. For instance, how about:
bool inStartup = false;
FooDelegate startup; // I don't know the real delegate type here
public event Startup
{
}
with the obvious firing code.
I'm not suggesting that it's a good thing to do, merely that the results aren't guaranteed, for precisely the same reason that:
application.SomeProperty = "fred";
Assert.AreEqual("fred", application.SomeProperty);
isn't guaranteed to work :)
Jon
Most likely it will fail and possibly catastrophicly, since you are essentially modifying a collection (the event handler delegates) while the collection is being iterated (by the invocation).
No, you're not modifying a collection - delegates are immutable. Calling Delegate.Combine returns a new delegate in the same way that String.Concat returns a new string. In other words, consider this:
string x = "Hello";
foreach (char c in x)
{
}
That won't go bang, because the original string being iterated through isn't changed. It's exactly the same when you invoke a delegate instance - it will iterate through its invocation list, and nothing will change that invocation list, whatever you do with it (barring out-and-out dirty reflection to set fields etc).
Jon
Comment preview