For example, I understand that I can't pass an event to a method or a constructor, but I don't understand why I can't. What makes an event different then a collection of delegates?
2 Answers
... while events look like delegate instances in terms of the way you express the add and remove operations, they're not.
Events are pairs of methods, appropriately decorated in IL to tie them together and let languages know that the methods represent events. The methods correspond to add and remove operations, each of which take a delegate instance parameter of the same type (the type of the event). What you do with those operations is pretty much up to you, but the typical use is to add or remove the delegate from a list of handlers for the event.
-
This is merely stating that event's aren't first class objects. The question asks why they aren't, which, as a premise, assumes that they're not. – Servy Jun 29 '16 at 02:50
-
1@Servy I think that knowing that Events are pairs of methods goes some way to explaining why, no? If you then want to know why they are like this then I would say the main reason is encapsulation. Invoking an event can only be done from within the class that declared the event. One could more or less emulate Events in c# by having a private Delegate member with a pair public accessor methods. Events in c# lend a conformity to this (rather than people creating similar, but different ways to solve this problem) and add some syntactic sugar so we can all type a bit less. – withakay Jun 29 '16 at 09:24
-
1That's justifying why events have as support for as much as they do. The question is why it stops there, and why you can't, for example, pass an event as a parameter to a method. You could absolutely design a language to do that, given that the event has been encapsulated. Your justification for why events couldn't' be supported more deeply is instead supporting the case that they could be (while in no way even addressing why they weren't). – Servy Jun 29 '16 at 12:56
-
I actually think the question is quite broad and open to some interpretation. You seem to want me to consider the reasoning behind event being the way there are, which I can't answer, I have not seen an explanation from the languages creators. Indeed changing the behavior has been proposed before now - https://github.com/dotnet/roslyn/issues/298 - but I am not sure that is the question the OP wanted answering, which is backed up by how he commented to Enigmativity answer. – withakay Jun 29 '16 at 20:42
-
If you think that the question is unanswerable then *you shouldn't have posted an answer to it*. I agree that the question is unanswerable. That's why I didn't post an answer to it. – Servy Jun 29 '16 at 20:47
-
1I agree, I couldn't answer the question as you had interpreted it. I answered in a way that I interpreted it. You may consider that wrong, others may too, that is of course why there is a voting system here :) – withakay Jun 30 '16 at 08:00
-
So you didn't interpret the question as asking why you can't pass an event to a method/constructor, because the question says, "I understand that I can't pass an event to a method or a constructor, but I don't understand why I can't." You responded to that by saying that he can't pass an event to a method or constructor, literally repeating what the question states it knows. – Servy Jun 30 '16 at 13:00
-
1You missed out a crucial part of the question: "What makes an event different then a collection of delegates?" which I think the answer covers fairly well, although I can't really take the credit for that. – withakay Jun 30 '16 at 18:15
An event is declared within a class to allow objects external to the class to be attach to the event and be notified about changes occurring within that class.
If it were a first-class citizen then the event could be invoked from an external class meaning that any rogue code with a reference to the event, of a Button
say, could cause the Click
event to be fired.
To prevent this events have special access rules that only allow the class that declares the event (and not even its own subclasses) to fire the event.
Hence, for this safety, events are not first-class citizens of the .NET Framework.

- 113,464
- 11
- 89
- 172
-
1While I think @withakay's answer is technically the correct answer, I think yours is a much better practical example of why you can't pass an event around. – Delta_50 Jun 29 '16 at 01:19
-
2This is completely false. You could make an event a first class citizen without allowing them to be invoked from outside of the type. By this logic a private field shouldn't be a first class citizen because it can't be accessed outside of a class, or a property with a private setter, or anything else that has a scope (i.e. basically everything). – Servy Jun 29 '16 at 02:52
-
1@Servy - I disagree. Events are very different to compare them to private fields. You can pass around the value/reference of a private field and use it with 100% of its features, but you can't do that with an event. – Enigmativity Jun 29 '16 at 05:40
-
@Enigmativity Yes, it's correct that you can't currently do that with events. The question is specifically asking *why you can't*. Stating that you can't is of course a premise of the question. You could absolutely allow it, and do so safely, C# simply does not do so. – Servy Jun 29 '16 at 12:58
-
-
1@Enigmativity And that explanation is completely false, as I specifically explained. The fact that an event can't be invoke from an external class in no way prevents the language from creating a construct to pass an event as an encapsulated object, so long as it maintains that external objects can't fire it (which is trivial to do). This is like claiming that methods can't be first class citizens because private methods can't be explicitly invoked from outside of the class that defines them. Given that methods *are* first class citizens, clearly this isn't an issue. – Servy Jun 30 '16 at 02:26
-
-
-
1I understand Servy as I find it very annoying that you cannot just even properly reference an event. it's impossible to write for example a 'OneShot' method that registers an handler and unregisters it after the first invokation. That's useful and it can't be done, which I find quite frustrating. – IARI Oct 13 '21 at 16:03
-
@IARI - You can do that quite trivially with Microsoft's Reactive Framework. Events can be made into observables, and an observable is a first-class citizen, and you can do `source.Take(1).Subscribe(x => { ... })` and it will automatically unregister after the first invocation. – Enigmativity Oct 13 '21 at 21:13
-
Yes, the point is, the react framework uses ugly hacks that work around the fact that events are not first class. Either you use reflection with a string literal or pass two extra lambdas that represent un/subscribing. There is not way to convert an event to an observable in a 'nice' way, where i Just reference the event - because an event cann ot be referenced. That alone is not very nice. – IARI Oct 15 '21 at 12:46
-
@IARI - The two un/subscribe lambdas ***are*** the nice way to do it, in my opinion. Unless you resort to reflection (which is ugly) then there's no other way because that how events have been defined in the language. And it's the Reactive Framework - we want to avoid confusion with React. – Enigmativity Oct 15 '21 at 21:57
-
You'Re right - sorry for misspelling here - we really do not want to confuse this with React ^^. – IARI Oct 17 '21 at 10:05
-
My though point is not at all about wether you should use Rx, your own implementation, or whatever framework. When you have maybe dozens or hundreds of events going, with native events the two lambdas are always needed for each of them if you want to convert them to something else that is more useful when you pursue more of a functional programming style. Boilerplate code that can be avoided by not using native events in the first place, but any Object capable of emitting signals to a maintained list of subscribers (like observables - or UnityEvent). That is all I want to say – IARI Oct 17 '21 at 10:06