Oren Eini

aka Ayende Rahien

Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,575
|
Comments: 51,188

Copyright ©️ Ayende Rahien 2004 — 2025

Privacy Policy · Terms
filter by tags archive
stack view grid view
  • architecture (606) rss
  • bugs (450) rss
  • challanges (123) rss
  • community (377) rss
  • databases (481) rss
  • design (893) rss
  • development (640) rss
  • hibernating-practices (71) rss
  • miscellaneous (592) rss
  • performance (397) rss
  • programming (1085) rss
  • raven (1442) rss
  • ravendb.net (526) rss
  • reviews (184) rss
  • 2025
    • May (7)
    • April (10)
    • March (10)
    • February (7)
    • January (12)
  • 2024
    • December (3)
    • November (2)
    • October (1)
    • September (3)
    • August (5)
    • July (10)
    • June (4)
    • May (6)
    • April (2)
    • March (8)
    • February (2)
    • January (14)
  • 2023
    • December (4)
    • October (4)
    • September (6)
    • August (12)
    • July (5)
    • June (15)
    • May (3)
    • April (11)
    • March (5)
    • February (5)
    • January (8)
  • 2022
    • December (5)
    • November (7)
    • October (7)
    • September (9)
    • August (10)
    • July (15)
    • June (12)
    • May (9)
    • April (14)
    • March (15)
    • February (13)
    • January (16)
  • 2021
    • December (23)
    • November (20)
    • October (16)
    • September (6)
    • August (16)
    • July (11)
    • June (16)
    • May (4)
    • April (10)
    • March (11)
    • February (15)
    • January (14)
  • 2020
    • December (10)
    • November (13)
    • October (15)
    • September (6)
    • August (9)
    • July (9)
    • June (17)
    • May (15)
    • April (14)
    • March (21)
    • February (16)
    • January (13)
  • 2019
    • December (17)
    • November (14)
    • October (16)
    • September (10)
    • August (8)
    • July (16)
    • June (11)
    • May (13)
    • April (18)
    • March (12)
    • February (19)
    • January (23)
  • 2018
    • December (15)
    • November (14)
    • October (19)
    • September (18)
    • August (23)
    • July (20)
    • June (20)
    • May (23)
    • April (15)
    • March (23)
    • February (19)
    • January (23)
  • 2017
    • December (21)
    • November (24)
    • October (22)
    • September (21)
    • August (23)
    • July (21)
    • June (24)
    • May (21)
    • April (21)
    • March (23)
    • February (20)
    • January (23)
  • 2016
    • December (17)
    • November (18)
    • October (22)
    • September (18)
    • August (23)
    • July (22)
    • June (17)
    • May (24)
    • April (16)
    • March (16)
    • February (21)
    • January (21)
  • 2015
    • December (5)
    • November (10)
    • October (9)
    • September (17)
    • August (20)
    • July (17)
    • June (4)
    • May (12)
    • April (9)
    • March (8)
    • February (25)
    • January (17)
  • 2014
    • December (22)
    • November (19)
    • October (21)
    • September (37)
    • August (24)
    • July (23)
    • June (13)
    • May (19)
    • April (24)
    • March (23)
    • February (21)
    • January (24)
  • 2013
    • December (23)
    • November (29)
    • October (27)
    • September (26)
    • August (24)
    • July (24)
    • June (23)
    • May (25)
    • April (26)
    • March (24)
    • February (24)
    • January (21)
  • 2012
    • December (19)
    • November (22)
    • October (27)
    • September (24)
    • August (30)
    • July (23)
    • June (25)
    • May (23)
    • April (25)
    • March (25)
    • February (28)
    • January (24)
  • 2011
    • December (17)
    • November (14)
    • October (24)
    • September (28)
    • August (27)
    • July (30)
    • June (19)
    • May (16)
    • April (30)
    • March (23)
    • February (11)
    • January (26)
  • 2010
    • December (29)
    • November (28)
    • October (35)
    • September (33)
    • August (44)
    • July (17)
    • June (20)
    • May (53)
    • April (29)
    • March (35)
    • February (33)
    • January (36)
  • 2009
    • December (37)
    • November (35)
    • October (53)
    • September (60)
    • August (66)
    • July (29)
    • June (24)
    • May (52)
    • April (63)
    • March (35)
    • February (53)
    • January (50)
  • 2008
    • December (58)
    • November (65)
    • October (46)
    • September (48)
    • August (96)
    • July (87)
    • June (45)
    • May (51)
    • April (52)
    • March (70)
    • February (43)
    • January (49)
  • 2007
    • December (100)
    • November (52)
    • October (109)
    • September (68)
    • August (80)
    • July (56)
    • June (150)
    • May (115)
    • April (73)
    • March (124)
    • February (102)
    • January (68)
  • 2006
    • December (95)
    • November (53)
    • October (120)
    • September (57)
    • August (88)
    • July (54)
    • June (103)
    • May (89)
    • April (84)
    • March (143)
    • February (78)
    • January (64)
  • 2005
    • December (70)
    • November (97)
    • October (91)
    • September (61)
    • August (74)
    • July (92)
    • June (100)
    • May (53)
    • April (42)
    • March (41)
    • February (84)
    • January (31)
  • 2004
    • December (49)
    • November (26)
    • October (26)
    • September (6)
    • April (10)
Comparison page for RavenDB and MongoDB
  previous post next post  
Dec 09 2007

Riddle me this...

time to read 1 min | 61 words

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.

Tweet Share Share 22 comments
Tags:
  • C#
  • Challanges

  previous post next post  

Comments

Ray Houston
09 Dec 2007
01:18 AM
Ray Houston

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? ;)

kiran
09 Dec 2007
02:15 AM
kiran

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 ?

Pedro Teixeira
09 Dec 2007
02:39 AM
Pedro Teixeira

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...

Dave Newman
09 Dec 2007
02:51 AM
Dave Newman

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?

Josh
09 Dec 2007
03:04 AM
Josh

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.

Anton
09 Dec 2007
04:02 AM
Anton

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.

Reshef Mann
09 Dec 2007
08:13 AM
Reshef Mann

I'm with josh. If he is correct, will it mean that we will have to share the rhino mocks license? :-)

Fred Hirschfeld
09 Dec 2007
09:08 AM
Fred Hirschfeld

Yes it will work but you will never see the second code being executed since the event only fires once. (Same as Dave)

Florin Sabau
09 Dec 2007
10:13 AM
Florin Sabau

The result of THAT piece of code is that you'll have a handler wired up to the Startup event/delegate. :P

Avish
09 Dec 2007
18:17 PM
Avish

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.

Sergio Pereira
09 Dec 2007
20:14 PM
Sergio Pereira

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.

efdee
09 Dec 2007
22:26 PM
efdee

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? :-)

Mik
10 Dec 2007
07:32 AM
Mik

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...

Mik
10 Dec 2007
08:10 AM
Mik

I guess it should work as follows:

  1. every time event is fired it gets the list of delegates to invoke and start calling it one by one...

  2. 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.

Petar Petrov
10 Dec 2007
09:41 AM
Petar Petrov

I guess it will only print "will it".

Ariel
10 Dec 2007
10:31 AM
Ariel

Whats 'application'? And hasn't the Application.Startup event already fired by the time your code runs?

Ayende Rahien
10 Dec 2007
10:33 AM
Ayende Rahien

Areil,

Application is a WPF app.

The question is about events, not about the specific case.

JLS
10 Dec 2007
13:57 PM
JLS

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.

Avish
10 Dec 2007
21:10 PM
Avish

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).

Jon Skeet
12 Dec 2007
09:11 AM
Jon Skeet

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

{

add

{

    if (!inStartup)

    {

        startup += value;

    }

    else

    {

        // Startup only occurs once, so let's just

        // execute the delegate now

        value();

    }

}

remove

{

    startup -= value;

}

}

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

CausticMango
12 Dec 2007
13:57 PM
CausticMango

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).

Jon Skeet
12 Dec 2007
15:46 PM
Jon Skeet

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)

{

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

Comments have been closed on this topic.

Markdown formatting

ESC to close

Markdown turns plain text formatting into fancy HTML formatting.

Phrase Emphasis

*italic*   **bold**
_italic_   __bold__

Links

Inline:

An [example](http://url.com/ "Title")

Reference-style labels (titles are optional):

An [example][id]. Then, anywhere
else in the doc, define the link:
  [id]: http://example.com/  "Title"

Images

Inline (titles are optional):

![alt text](/path/img.jpg "Title")

Reference-style:

![alt text][id]
[id]: /url/to/img.jpg "Title"

Headers

Setext-style:

Header 1
========
Header 2
--------

atx-style (closing #'s are optional):

# Header 1 #
## Header 2 ##
###### Header 6

Lists

Ordered, without paragraphs:

1.  Foo
2.  Bar

Unordered, with paragraphs:

*   A list item.
    With multiple paragraphs.
*   Bar

You can nest them:

*   Abacus
    * answer
*   Bubbles
    1.  bunk
    2.  bupkis
        * BELITTLER
    3. burper
*   Cunning

Blockquotes

> Email-style angle brackets
> are used for blockquotes.
> > And, they can be nested.
> #### Headers in blockquotes
> 
> * You can quote a list.
> * Etc.

Horizontal Rules

Three or more dashes or asterisks:

---
* * *
- - - - 

Manual Line Breaks

End a line with two or more spaces:

Roses are red,   
Violets are blue.

Fenced Code Blocks

Code blocks delimited by 3 or more backticks or tildas:

```
This is a preformatted
code block
```

Header IDs

Set the id of headings with {#<id>} at end of heading line:

## My Heading {#myheading}

Tables

Fruit    |Color
---------|----------
Apples   |Red
Pears	 |Green
Bananas  |Yellow

Definition Lists

Term 1
: Definition 1
Term 2
: Definition 2

Footnotes

Body text with a footnote [^1]
[^1]: Footnote text here

Abbreviations

MDD <- will have title
*[MDD]: MarkdownDeep

 

FUTURE POSTS

  1. Optimizing the cost of clearing a set - 3 days from now
  2. Scaling HNSW in RavenDB: Optimizing for inadequate hardware - 5 days from now

There are posts all the way to May 14, 2025

RECENT SERIES

  1. RavenDB News (2):
    02 May 2025 - May 2025
  2. Recording (15):
    30 Apr 2025 - Practical AI Integration with RavenDB
  3. Production Postmortem (52):
    07 Apr 2025 - The race condition in the interlock
  4. RavenDB (13):
    02 Apr 2025 - .NET Aspire integration
  5. RavenDB 7.1 (6):
    18 Mar 2025 - One IO Ring to rule them all
View all series

RECENT COMMENTS

  • But in case you have nullability checks enabled (i.e. `<Nullable>enable</Nullable>`), then you'll have a compiler warning on ...
    By Samyon Ristov on The null check that didn't check for nulls
  • Grok wasn't *wrong*. It only said that `_items` can't be null for the condition to evaluate to `true`, but didn't say anythi...
    By Johannes Egger on The null check that didn't check for nulls
  • When I started enabling NRT, I remember I was initially confused when all variables (for reference types) declared with `var`...
    By riccardo on The null check that didn't check for nulls
  • That is surprising - I think of var as a shorthand that does not affect the final result of the compilation. I wouldn't expec...
    By Chris B on The null check that didn't check for nulls
  • "It is also about as friendly as a monkey with a sore tooth and an alcohol addiction." And I have to clean my monitor.
    By Tim on When racing the Heisenbug, code quality goes out the Windows

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}