I think you're confusing ASP.NET's (mis)use of events, with plain ol' event handling.
We'll start with plain ol' event handling. Events is a (yet another) way of fulfilling the "Open [for extension]/Closed [for modification]" principle. When your class exposes an event, it allows external classes (perhaps classes that aren't even thought of, much less built, yet) to have code run by your class. That's a pretty powerful extension mechanism, and it doesn't require your class to be modified in any way.
As an example, consider a web server, that knows how to accept a request, but doesn't know how to process a file (I'll use bi-directional events here, where the handler can pass data back to the event source. Some would argue that's not kosher, but it's the first example that came to mind):
class WebServer {
public event EventHandler<RequestReceivedEventArgs> RequestReceived;
void ReceiveRequest() {
// lots of uninteresting network code here
var e = new RequestReceivedEventArgs();
e.Request = ReadRequest();
OnRequestReceived(e);
WriteResponse(e.Response);
}
void OnRequestReceived(RequestReceivedEventArgs e) {
var h = RequestReceived;
if (h != null) h(e);
}
}
Without changing the source code of that class - maybe it's in a 3rd party library - I can add a class that knows how to read a file from disk:
class FileRequestProcessor {
void WebServer_RequestReceived(object sender, EventArgs e) {
e.Response = File.ReadAllText(e.Request);
}
}
Or, maybe an ASP.NET compiler:
class AspNetRequestProcessor {
void WebServer_RequestReceived(object sender, EventArgs e) {
var p = Compile(e.Request);
e.Response = p.Render();
}
}
Or, maybe I'm just interested in knowing that an event happened, without affecting it at all. Say, for logging:
class LogRequestProcessor {
void WebServer_RequestReceived(object sender, EventArgs e) {
File.WriteAllText("log.txt", e.Request);
}
}
All of these classes are basically "injecting" code in the middle of WebServer.OnRequestReceived
.
Now, for the ugly part. ASP.NET has this annoying little habit of having you write event handlers to handle your own events. So, the class that you're inheriting from (System.Web.UI.Page
) has an event called Load
:
abstract class Page {
public event EventHandler Load;
virtual void OnLoad(EventArgs e) {
var h = this.Load;
if (h != null) h(e);
}
}
and you want to run code when the page is loaded. Following the Open/Closed Principle, we can either inherit and override:
class MyPage : Page {
override void OnLoad(EventArgs e) {
base.OnLoad(e);
Response.Write("Hello World!");
}
}
or use eventing:
class MyPage : Page {
MyPage() {
this.Load += Page_Load;
}
void Page_Load(EventArgs e) {
Response.Write("Hello World!");
}
}
For some reason, Visual Studio and ASP.NET prefer the eventing approach. I suppose you can then have multiple handlers for the Load
event, and they would all get run auto-magically - but I never see anyone doing that. Personally, I prefer the override approach - I think it's a bit clearer and you'll never have the question of "why am I subscribed to my own events?".