Introduction
If you are a beginner .NET developer and you have trouble working with events - like me -, then this tip is for you. After immersing myself in articles and videos that address events in .NET, I managed to summarize these articles in a way that helped me understand its structure and hopefully, it will help you as well.
Background
Event is the way used by .NET to notify subscribers about a change or action in the event owner class. As shown in the following graph, the event owner will raise the event without knowing (or caring) about the subscribers. Once raised, .NET will send the notification for each subscriber. The subscriber should create an event handle. Event handle is simply a function that will be run whenever the event is raised.
Using the Code
The events in .NET are based on the delegate structure. Delegate is a pointer to one or more functions that will be called together as in the following snippet.
static void WriteToFile(string s){
File.Append(s);
}
static void WriteToLog(string s){
log.info(s);
}
delegate void writeDelegate(string x);
static void Main(string[] args){
writeDelegate x = WriteToFile;
x+= WriteToLog;
x+= (a) => Console.WriteLine(a);
x("Hello World!");
}
So the old way to define an event is by creating a delegate, then define an event based on this delegate and finally raise the event. The following code raises event if the salary is more than 1000
.
class Person{
public delegate void SalaryLimit(int s);
public event SalaryLimit IamRich;
private int salary;
public int Salary{
get {return salary;}
set {
salary = value;
if (salary > 1000){
if (IamRich != null){
IamRich(salary);
}
}
}
}
}
Instead of defining a custom delegate, we can directly use EventHandler
and EventHandler<TEventArgs>
, These are two predefined delegates with a slightly different signature that can be used with events. The first is usually used if there is no data to pass with the event as follows:
class Person{
public event EventHandler TimeToSleep;
if (time is late){
if (TimeToSleep != null) {
TimeToSleep(this, Eventargs.Empty)
}
}
}
If we want to pass data to subscribers along the event, we have to use EventHandler<TEventArgs>
after creating a new class that inherits from EventArgs
and add your parameter.
class AddressEventArgs: EventArgs {
public string Address {get; set;}
}
Now define your event as follows:
class Person{
public event EventHandler<AddressEventArgs> AddressChange;
private string address;
public string Address{
get { return address;}
set { address = value;
AddressEventArgs e = new AddressEventArgs();
e.Address = address;
onAddressChange(e);
}
}
protected virtual void onAddressChange(AddressEventArgs e){
EventHandler<AddressEventArgs> handler = AddressChange;
if (handler != null){
handler(this, e);
}
}
}
On the other hand, the subscribers have to create an event handle which might be a function or a lambda expression. This handle will be called whenever the event is raised.
static void Main(string[] args){
Person p = new Person();
p.AddressChange += (o, e) => Console.WriteLine("My new address is " + e.Address);
p.AddressChange += p_addressChange;
}
static void p_addressChange(object o, AddressEventArgs e){
Console.WriteLine("My new address is " + e.Address);
}
Conclusion
This is my first tip here, hopefully I will get constructive feedback to enhance it. Thanks for your time.
History
- March 15, 2015: Initial version
- March 20, 2015: add the source code and fix some spell errors