Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#
I was asked this question in an interview, and either I'm suffering from brain-lock or just plain dumb, but I didn't have an answer.

Anyone?

Marc

Posted 12-Mar-09 8:11am
Marc Clifton404.1K
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

I revisited your question after looking at your last question.
 
First note is: all, absolutely all delegate instances in .NET are multicast. I mean, some delegate instances have only one handler in its invocation list, but in all such cases "+=" creates a multicast interface instances with two handlers. They all have an invocation list as a member, even each member of invocation list, paradoxically. What is interesting, "+=" never adds anything to existing delegate instance: delegate instances are immutable. A brand-new delegate instances and a brand new reference to it is created in response to "+=". The immutability of delegate instance is done to improve multithreading. Finally, why do I talk about delegate instances? Take a type of a delegate instance. Is it a delegate type? No! A run-time type of a delegate instance is some… class. Get a type and use Reflection to see. I write about it in my article Dynamic Method Dispatcher[^].
 
Now, let's move to events. Here is my statement: each and every behavior of events can be implemented using just delegate and delegate instances, without any exclusion. Not visa versa. So, what's the benefits of events over delegate instances? Limitations!
 
For example: whatever you do, you can invoke event only in its declaring class, nowhere else. You cannot even invoke an event in a derived class, which is very unusual, because in other cases, every possibility is dictated by access modifiers and scope, nothing else. Why is that? I understood it well answering CodeProject questions. Many asked: "how can I call (I say: "invoke, not call" — SA) the event Button.Click?".
 
(Amazing logic: when a compiler says: "operation X is not allowed", typical first question is "how to do operation X"? We have a proverb: "If prohibited but very desirable then allowed" Smile | :) .)
 
The event Button.Click is already invoked — in the libraries. Invocation of it somewhere else, even through a class derived from Button is never really needed; one can always call some method in two places: from the Button.Click handler and somewhere else, but it would not cause invocation (which would cause the call of each handler in the invocation list), and hence it would not disrupt intended behavior of UI event system.
 
Invocation of this event would be foolish. And the event is what it is: a fool-proof variant of delegate instances.
 
And UI is not the only field of application of events. Events are used when the limitations of events are needed.
 
—SA
  Permalink  
v3
Comments
Pete O'Hanlon at 29-Feb-12 6:04am
   
Good answer. And I didn't know that events couldn't be used in a derived class - mind you, it's not something I've ever needed to try, so good job again. My 5.
 
[Edit]My memory isn't 100% faulty - it is possible to mark an event as virtual, allowing classes to override them - I know this doesn't go against what you said, but I knew there was something about events and derived classes tickling my memory.
SAKryukov at 29-Feb-12 15:09pm
   
Thank you, Pete.
 
Oh, with virtual events it's even more unusual. You don't remember it clearly, just because we rarely use them. Me too.
In brief: virtual even cannot be invoked even in the declaring class.
 
More exactly, you can just add "virtual" and trigger it in the same class. But this "virtual" would be useless without "add" and "remove" methods (I would suggest prohibit "virtual" without add/remove by syntax): such event could not be overridden in any way in derived class. So, we should only consider virtual/abstract events with add/remove which could be overridden in a derived class. But syntax will not allow you to invoke such event at all, even in the declaring class!
 
Why such limitation in invocation? Because it would defeat the purpose of add/remove. You can only trigger the even indirectly, by invocation of the implementing delegate instance which gets handlers to be added to its invocation list via "add". And, from this moment, the door to abuse is opened again, because one could foolishly give too much access to this implementing delegate instance, use it outside of the declaring class or outside of derived classes, etc. But this would be the same thing as excessive access to any other implementation detail, violation of good encapsulation practice. And practically, this is fine: if some developer manages to struggle through the syntax for virtual event with overridden add/remove successfully, we can hope this person knows what she or he is doing.
 
[EDIT]
I clarified the sentence where I explain the role of implementing delegate instance and "add" method. This instance is not passed through "add", but a handler is passed to "add" or "remove". This is a different delegate instance, used to change implementing delegate instance. The Microsoft article referenced above shows the implementation.
[END EDIT]
 
Well, this topic could be a matter of another short article. Would it be interesting?
 
I would like to close-up this discussion for now. Please see:
http://msdn.microsoft.com/en-us/library/hy3sefw3.aspx,
http://blogs.msdn.com/b/samng/archive/2007/11/26/virtual-events-in-c.aspx.
 
Please also see my comment to the answer by Shameel.
--SA
Pete O'Hanlon at 29-Feb-12 15:17pm
   
Thanks for that. That was an interesting detour into the more esoteric sides of the language, and why constraints are placed by the language designers.
SAKryukov at 29-Feb-12 15:48pm
   
My pleasure.
--SA
Espen Harlinn at 29-Feb-12 15:02pm
   
5'ed!
SAKryukov at 29-Feb-12 15:11pm
   
Thank you, Espen.
Please see new comments in response to the discussion with Shameel and Pete.
--SA
Espen Harlinn at 29-Feb-12 15:18pm
   
Well done :)
Looking at an 'event' implementation using reflector illustrates this pretty well too.
SAKryukov at 29-Feb-12 15:49pm
   
Thank you again.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 5

Are you are already aware Marc, the event mechanism is just a syntactic sugar over the delegate model, just like a Property is a syntactic sugar over getters and setters.
 
As SAKryukov has rightly pointed out, events are all about restrictions. The compiler enforces certain restrictions over the delegates declared with the 'event' modifier so that only the declaring class can invoke the event.
 
It also helps us (the old VB programmers) to follow the code easily, you have a mental mapping that an event signifies the change of state in an object whereas delegates do not necessarily imply that.
  Permalink  
Comments
SAKryukov at 29-Feb-12 13:50pm
   
I must note that the events do not imply change in state; no more than delegate instances do; neither in "implied" semantics nor in common practice.
 
I would not call Button.Click semantically carrying a meaning of a change in state, for a stateless button. A button with states could do in: PressingDown, PressedDown, BeingReleased, Released. A usual button gives no access to states, because it is returned to the same state after click, and this is usual. It only can be used for a state change (and I always vote for not doing it), but not in UI -- in the model where the developer plays the role of the user of the UI.
 
In other words, the topic of "change in state" is totally neutral to delegate and events. Semantically, event is event, state is state, and the change in state is just one of possible semantics for the events, like in LayoutChanged.
 
If you want to outline the difference in uses, you could note that delegate instances are not used for events at all. But this is not related to the nature of events and delegate instances. It's just because events are already used to carry the event semantics. Why using any other tool for that? But delegate instances could be used to carry event semantics as well; it's just nobody need it.
 
The fundamental role of delegates is different -- serving to represent methods as first-class objects, in the spirit of functional programming.
 
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Events can make sure: using += or -=, but not = directly.
  Permalink  
Comments
Pete O'Hanlon at 6-Dec-10 15:12pm
   
What does this have to do with Marc's question? He's what I would call a .NET expert, and your question doesn't add anything. He's well aware of how you hook up events; his question is why do we have events when you can achieve the same thing with a multi cast delegate.
SAKryukov at 28-Feb-12 22:43pm
   
Exactly. I recently re-visited this question and suggested a real answer. Please see if you are curious.
--SA
Pete O'Hanlon at 29-Feb-12 6:03am
   
Now when you put your response like that, I actually want to go and read your answer. It's just the right tone to get me interested. Good job.
Marc Clifton at 29-Feb-12 7:20am
   
SAKryukov is trolling - I posted that question 3 years ago, then I posted a question yesterday, and now it seems like he's taken it upon himself to find other questions I've asked. I suppose I should take the high road and assume he's trying to be helpful.
Pete O'Hanlon at 29-Feb-12 7:30am
   
Ahhh, I see. I like the spread of time between your posting of questions;)
Marc Clifton at 29-Feb-12 7:39am
   
Well, like you said, I'm what you'd call a .NET expert, hahahaha! :-D
SAKryukov at 18-Dec-10 18:45pm
   
This is not exactly the point (level of expertize, etc. -- always difficult to estimate). The real problem with this answer is this: this statement fails to disclaim, that this is only one (randomly picked) difference, not comprehensively or formally defining real difference. Also, this does not help to understand the essence of += or -= (multicast feature which Marc might understand (see the question title). Illusory knowledge is ALWAYS MUCH WORSE than no knowledge. Sometimes, illusory answer is worse than no answer at all.
  Print Answers RSS
0 OriginalGriff 587
1 Sergey Alexandrovich Kryukov 479
2 Maciej Los 305
3 Mathew Soji 195
4 Richard MacCutchan 145
0 OriginalGriff 7,356
1 Sergey Alexandrovich Kryukov 6,712
2 DamithSL 5,461
3 Manas Bhardwaj 4,916
4 Maciej Los 4,475


Advertise | Privacy | Mobile
Web04 | 2.8.1411023.1 | Last Updated 29 Feb 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100