Click here to Skip to main content
15,881,687 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
What exactly is an event and an event handler?

In this C# line

C#
context.BeginRequest += context_BeginRequest;


Where is the event and the event handler? How do you call the left part and and right part of the +=?
Posted
Comments
BillWoodruff 24-Oct-14 0:09am    
Do keep in mind that learning to transform being irritated with realizing you don't know how to understand/use/achieve something in programming ... yet ... into a relatively calm ... or even positively excited ... state of mind ... is: something that almost all of us have to develop through experience, through learning to separate frustration with doing and knowing from any "inner judgement" that: because we can't quite grasp whatever it is we are somehow deficient, stupid, not talented, etc.

For most of us, that is a life's work: learning how to learn. And, one of the wonderfully challenging things about programming is that you almost always need, these days, to keep actively self-educating, and learning new skills, and tools, because the pace of innovation in hardware, and software, is so rapid.

Look at this CP survey:

http://www.codeproject.com/Surveys/1688/Whats-the-best-part-about-being-a-software-develop.aspx

The highest percentage of votes cast by survey takers (programmers) in voting on the statement: "What's the best part about being a software developer?" was: "There's always something new to learn" !

In my opinion technical learning is a skill that can be always developed further. For any one individual what may be helpful may vary: one person may learn best by intense "marathons" of single-minded focus; other people (like me), learn best through alternating top-down learning with bottom-up coding to solve problems I set for myself.

Some people post here with specific questions to get answers, and be "on their way:" that's fine. Other people post here for assistance with learning to program, or help with identifying where they are stuck with a specific programming error, or even to try and make progress in being able to conceptualize an idea they have that they can't quite translate into a UI and code: that's fine too.

The great advantage of being in a team with other people at varying levels of skill, including those far above your own, is that you get a chance, through observing others, to understand what may work best for you in learning, and improving ... not to mention getting where and how you are confused ... at any given moment ... identified clearly. What is identified clearly can, imho, be worked on much more skilfully than what what one cannot even conceptualize.

... end of sermon ... :) If only I could "live up to" my own words !
Bastien Vandamme 24-Oct-14 1:04am    
I agree with this. By the way the survey doesn't explain what kind of new think people like to learn. Will you invest time to learn something if I say you this think will be obsolete soon? Learning science like mathematics, algorithms, statistics basic and common concept of OOP, SOA, AOP and so is not the same as learning engineering like instructions of a brand x product build by a company.

There is a difference between, for instance, SQL and an SQL server or C# and .NET or a specific library of .NET.

The survey should also ask what's the worst part about being a software developer?
BillWoodruff 24-Oct-14 1:32am    
I think when you try to think about how any specific individual would have motivation, or be enthusiastic, about learning any new technology you would need to have a lot of information about that individual, about their character, their cognitive style, their social/cultural/socio-economic status in their culture.

But, fortunately, every time you learn some technology deeply, in my opinion: you increase your general ability to learn, your confidence in future mastery given a new challenge. And, interestingly, there's some good evidence from the study of the anthropology of education in cultural context that indicates that "discontinuities" are uniquely valuable. I'd like to see a programmer who is a one-trick pony, like a master of C#, learn a radically different approach, like declarative programming (F#, for example).

That said, I think there is a certain type of higher-level learning (mathematics, formal computer science) abstracted from any specific computer language that will pay off across a broad-range of new learning challenges in programming. I regret I have not had as much of that as I would like since I jumped into programming at age forty, and I admire people like Sergey who, obviously, can think on a much higher-level of abstraction about programming ... even if I can't fully understand what he writes :)

So far, it's pretty simple: context.BeginRequest is the event instance. This is the class which has invocation list. The '+=' operation adds the handler (actually, a delegate instance), this that invocation list. In your case, the handler is context_BeginRequest. Interestingly, event instances are immutable, so, in fact, '+=' operator creates a brand new instance of the event instance and adds all handlers already found in the invocation list before the operation, adds a new handler are returns that new event instance. This way, the member context.BeginRequestNaturally, which is the reference object, looses its referential identity. Eventually, old event instance object, as it becomes inaccessible, will be garbage-collected. This is done to improve multithreading properties of event instances.

You can read about it, as well as some other interesting facts, in my article, the section 4.1 On the Nature of Delegate Instance.

Now, as right part is just the method, you can call it method the same way as any other method. The object on left is the event instance. For event instances, there is no such concept as "call". It can be invoked, so all elements of the invocation list will be called. That's why there is no a "call". Moreover, the invocation (BeginRequest.Invoke(/*...*/) cannot be done anywhere except the declared type. If the source code of this type is yours, you can invoke the event. This is the important fool-proof feature of .NET, to guard naive developers from invoking an event instance when it is not needed. You can read about it in my past answer: UserControl custom event[^].

—SA
 
Share this answer
 
Comments
BillWoodruff 23-Oct-14 22:20pm    
+5 I hope the OP can digest this level of content. Aside: I consider it a weakness of C# that an EventHandler can be called directly, rather than ONLY being "raised" in the usual manner through 'On......(someValidObject, someValidEventArgTypeInstance):

// legal !
btnSomeButton_Click(null, null);

I've seen many (bright people) beginning students of C# have difficulty "getting" Events, and Delegates, not to mention the fact that 'Action and 'Func are Delegate Types.

What if ... C# required a special form of declaration for an event handler method:

private EventHandlerMethod SomeButton_Click(object sender, EventArgs e) { ... }

Well :) ... yes, that's quite a fantasy, and I imagine Anders might get a chuckle reading it !
Sergey Alexandrovich Kryukov 23-Oct-14 22:32pm    
Thank you, Bill.

You see, too much protection would be pointless. Let's assume that a handler is a special construct. It is almost so, if you, say, allow only anonymous handlers:
someObject.someEvent += (sender, eventArgs) =>
{ // what's inside the '{}' cannot called from anywhere except someEvent.Invoke
//...
}


Very good. But nothing prevents from something like
someObject.someEvent += (sender, eventArgs) =>
{ // what's inside the '{}' cannot called from anywhere except someEvent.Invoke
RealHandler(); // one place to call
}

//...

RealHandler(); // ... another call


And where is your protection? By definition, RealHandler() cannot be anything different from a regular method.
And nothing can protect a fool from writing any stupid thing like
A[0] = 0;
A[1] = 1;
A[2] = 2;
//... I only today saw something like that in Q&A


The really good practice would be using only anonymous handlers in cases where some code should only be called. This is not always the case.

—SA
BillWoodruff 23-Oct-14 22:56pm    
Indeed, I really like the fact that a Lambda Expression is much more of a "private" thing, in the sense that it cannot be removed from the invocation list.

My "fantasy" only pertained to how the language itself might constrain the syntax of EventHandlers written as named methods; I wasn't thinking of any change/limitation to the nature of the multi-cast Event Type itself.

The fact that you can "get away with" writing a valid EventHandler like this:

private EventHandler someButton_Click(object sender, EventArgs e)
{
MessageBox.Show("strange indeed ?");
// no return statement: compile error !
return null;
}

... well ... this is the kind of thing that bright students come up with, as they struggle with Delegates/Events/EventHandlers in C#.

The technique I use if I want to create an Event that can only be subscribed to once (an Event "singleton," as it were) is to use an 'Action or 'Func defined as 'private in a Class, and assigned to only in the CTor of the Class.
Sergey Alexandrovich Kryukov 23-Oct-14 23:11pm    
That is pretty strange, return a delegate from a method which can be used as an event handler (as I can only know from context). Normal delegate type used in events is void. How could it be used? I can imagine it, but I don't see your point.

One important thing: events subscription is a way to create memory leaks.
In fact, I also use the techniques when an event handlers are never removed. I have serious arguments for such technique. I face arguments saying that unsubscribing is the way to avoid memory leaks, but I disagree. As to "only in constructor of the class" (which class, though?) would be a too big limitation. Imagine the classes with many events. To many constructors or too many constructor parameters is a bad thing. For an event instance, there is nothing better than making them public/internal members; this what they are designed for. Having initializing them in constructor defeats the purpose of events, reducing the technique the the technique of using "regular" delegate instances. That's why event is more restrictive construct than the delegate instance; it is designed to be a directly exposed member. And the protection is: no calls, no assignments, only adding/removing handlers. If I designed it, I would allow removing handlers, for some, it would be easier; and there is nothing fundamentally bad with removing handlers.
—SA
BillWoodruff 23-Oct-14 23:47pm    
I think there are times that the C# Event/Delegate facility is great as-is in terms of inherent functionality, and other times ... when the programmer, perhaps, wants more privacy/encapsulation/restriction of functionality ... more difficult to work with than it (ideally) should be.

But, I do see understanding the mechanism/syntax is complex, and bewildering for many people. Perhaps you are familiar with the rather "famous" brief analogy on Delegates by Chris Sells:

https://www.sellsbrothers.com/writing/delegates.htm

I find that very few of the students I've had can make any sense out of that; yet, that's held up as a shining example of explanation all over the web in the C#-verse (or, it was several years ago, anyhow).

Here's the kind of pattern I use when I want a "singleton" EventHandler:

   // in some other Class/Form/NameSpace, etc.
   private Action<string> NotifyTextEntered { set; get; }

   // restrict to one Notify function instance
   public void setNotifyTextEntered(Action<string> theNotifiyFunc)
   {
      if (NotifyTextEntered != null) return;

      NotifyTextEntered = theNotifiyFunc;
   }

// the notification function might be invoked like this:

    private void textBox1_KeyUp(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
      {
        if(NotifyTextEntered != null) NotifyTextEntered(textBox1.Text);
      }
    }

Then, naturally, the whatever that creates the instance of the Class/Form that contains this code injects a Func like so:

   someClassOrObject.setNotifyTextEntered(s => MessageBox.Show(s));
   someClassOrObject.setNotifyTextEntered(s => MessageBox.Show("will never be called ... but will not throw error in this implementation"));
You need to do at least a minimum of research, and thinking for yourself, before you ask other people to explain fundamental concepts in .NET and C# Object-Oriented-Development to you ... as if you are not surrounded by all the resources you need on the internet.

Start with this excellent CodeProject article: [^].

Alternate studying with experimenting with putting some Controls, like a Button, a TextBox, on a Windows Forms, and create basic Event Handlers, for example, for 'Click, or 'TextChanged, using the Property Browser (F4).

Study this tutorial on MSDN: [^].

As you alternate study and experimentation, think about what in your "real world" daily life might correspond to an Event, and an EventHandler: an alarm clock going off; your telephone ringing; a smoke alarm ?

When you are comfortable creating EventHandlers for Control events in C#, then move on to learning how to create your own Event, and understanding what a Delegate is, and how Delegates in .NET implement multi-casting: the notification of all Event "subscribers."

And, think about the fact that: if an Event has "subscribers," and subscribers can be added, and deleted, then there must be something that "maintains" a list of the current subscribers. In .NET the term for this list of things-to-be-notified is called the "invocation list:" and the special functions += and -= add, and remove, a subscriber to the Event. In C# you have very limited access to this invocation list (other languages offer different types of access).

And, as you have specific questions, preferably involving code you have written yourself: come back here and ask them.
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 23-Oct-14 22:07pm    
In principle, you answered, my 5.
However, the problem is: events is the field when MSDN documentation is frustrating. It creates so many illusions in the developers.
One of the myths (remember you posts about event "ceremonies"?) is totally redundant new operator for creating a delegate instance using the method name. (And extremely bad auto-generated code supports such myths.)
I still did not find time to participate in that thread, but I have a lot to tell. Probably, you did not least all "ceremonies" and mix "ceremonies" with recommendations and rules, but I generally agree with you. Some of the posts on that threads are also based on incomplete understanding of this topic.

That's why I decided to write a section in my article to clarify things, which are not only poorly explained in MSDN, but also not easy to explain.

Please see my answer.

—SA
BillWoodruff 23-Oct-14 22:21pm    
I will read the (new ?) section of your article with interest.
Sergey Alexandrovich Kryukov 23-Oct-14 22:39pm    
Well, of course you could read more, spend more time, write some research code and do investigation using the debugger and decompilation. It could tell you a lot. Besides, the CRL standard (ECMA, freely available), is more detailed. But not everyone is qualified and patient enough do conduct such research, which is not so difficult, but pretty sophisticated.

So, of course, part of your question makes sense, because, as I say, MSDN documentation on this topic is neither clear nor complete.

From the other hand, your first question, about what is event and what is instance is elementary, you could always read about it.

—SA
BillWoodruff 23-Oct-14 22:42pm    
It appears that an attitude problem is part of what is keeping you from getting busy learning. Every minute you spend telling yourself "it is not clear," or, "it is difficult," is a minute you have wasted. Every time you feel "entitled" to be angry at people you imagine/think are not trying to help you, is a small piece of your life thrown away.
Sergey Alexandrovich Kryukov 23-Oct-14 23:12pm    
Golden words!
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900