Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article shows how to work with events in .NET using the EventHandler delegate, the EventHandler<TEventArgs> delegate, and a custom delegate, with examples for events with and without data.
Prerequisites
Familiarize yourself with the concepts in the Events article.
Raise an event without data
These steps create a Counter class that fires a ThresholdReached event when a running total reaches or exceeds a threshold.
Declare the event using the EventHandler delegate.
Use
EventHandlerwhen your event doesn't pass data to the handler:public event EventHandler? ThresholdReached;Public Event ThresholdReached As EventHandlerAdd a
protected virtualmethod (Protected Overridablein Visual Basic) to raise the event.This pattern lets derived classes override the event-raising behavior without directly invoking the delegate. In C#, use the null-conditional operator (
?.) to guard against no subscribers (in Visual Basic,RaiseEventhandles this automatically):protected virtual void OnThresholdReached(EventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As EventArgs) RaiseEvent ThresholdReached(Me, e) End SubCall the raise method when the condition is met.
Pass Empty because this event carries no data:
if (_total >= _threshold) { OnThresholdReached(EventArgs.Empty); }If (_total >= _threshold) Then OnThresholdReached(EventArgs.Empty) End IfSubscribe to the event using the
+=operator (in Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedDefine the event handler method.
Its signature must match the EventHandler delegate—the first parameter is the event source and the second is EventArgs:
static void c_ThresholdReached(object? sender, EventArgs e) { Console.WriteLine("The threshold was reached."); Environment.Exit(0); }Sub c_ThresholdReached(sender As Object, e As EventArgs) Console.WriteLine("The threshold was reached.") Environment.Exit(0) End Sub
The following example shows the complete implementation:
class EventNoData
{
static void Main()
{
Counter c = new(new Random().Next(10));
c.ThresholdReached += c_ThresholdReached;
Console.WriteLine("press 'a' key to increase total");
while (Console.ReadKey(true).KeyChar == 'a')
{
Console.WriteLine("adding one");
c.Add(1);
}
}
static void c_ThresholdReached(object? sender, EventArgs e)
{
Console.WriteLine("The threshold was reached.");
Environment.Exit(0);
}
}
class Counter(int passedThreshold)
{
private readonly int _threshold = passedThreshold;
private int _total;
public void Add(int x)
{
_total += x;
if (_total >= _threshold)
{
OnThresholdReached(EventArgs.Empty);
}
}
protected virtual void OnThresholdReached(EventArgs e)
{
ThresholdReached?.Invoke(this, e);
}
public event EventHandler? ThresholdReached;
}
Module EventNoData
Sub Main()
Dim c As New Counter(New Random().Next(10))
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
Console.WriteLine("press 'a' key to increase total")
While Console.ReadKey(True).KeyChar = "a"
Console.WriteLine("adding one")
c.Add(1)
End While
End Sub
Sub c_ThresholdReached(sender As Object, e As EventArgs)
Console.WriteLine("The threshold was reached.")
Environment.Exit(0)
End Sub
End Module
Class Counter
Private ReadOnly _threshold As Integer
Private _total As Integer
Public Sub New(passedThreshold As Integer)
_threshold = passedThreshold
End Sub
Public Sub Add(x As Integer)
_total += x
If (_total >= _threshold) Then
OnThresholdReached(EventArgs.Empty)
End If
End Sub
Protected Overridable Sub OnThresholdReached(e As EventArgs)
RaiseEvent ThresholdReached(Me, e)
End Sub
Public Event ThresholdReached As EventHandler
End Class
Raise an event with data
These steps extend the previous Counter example to raise an event that includes data—the threshold value and the time it was reached.
Define an event data class that inherits from EventArgs.
Add properties for each piece of data you want to pass to the handler:
public class ThresholdReachedEventArgs : EventArgs { public int Threshold { get; set; } public DateTime TimeReached { get; set; } }Class ThresholdReachedEventArgs Inherits EventArgs Public Property Threshold As Integer Public Property TimeReached As Date End ClassDeclare the event using the EventHandler<TEventArgs> delegate, passing your event data class as the type argument:
public event EventHandler<ThresholdReachedEventArgs>? ThresholdReached;Public Event ThresholdReached As EventHandler(Of ThresholdReachedEventArgs)Add a
protected virtualmethod (Protected Overridablein Visual Basic) to raise the event.This pattern lets derived classes override the event-raising behavior without directly invoking the delegate. In C#, use the null-conditional operator (
?.) to guard against no subscribers (in Visual Basic,RaiseEventhandles this automatically):protected virtual void OnThresholdReached(ThresholdReachedEventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs) RaiseEvent ThresholdReached(Me, e) End SubPopulate the event data object and call the raise method when the condition is met:
if (_total >= _threshold) { ThresholdReachedEventArgs args = new ThresholdReachedEventArgs(); args.Threshold = _threshold; args.TimeReached = DateTime.Now; OnThresholdReached(args); }If (_total >= _threshold) Then Dim args As New ThresholdReachedEventArgs With { .Threshold = _threshold, .TimeReached = Date.Now } OnThresholdReached(args) End IfSubscribe to the event using the
+=operator (in Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedDefine the event handler.
The second parameter type is
ThresholdReachedEventArgsinstead of EventArgs, which lets the handler read the event data:static void c_ThresholdReached(object? sender, ThresholdReachedEventArgs e) { Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}."); Environment.Exit(0); }Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs) Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached) Environment.Exit(0) End Sub
The following example shows the complete implementation:
class EventWithData
{
static void Main()
{
CounterWithData c = new(new Random().Next(10));
c.ThresholdReached += c_ThresholdReached;
Console.WriteLine("press 'a' key to increase total");
while (Console.ReadKey(true).KeyChar == 'a')
{
Console.WriteLine("adding one");
c.Add(1);
}
}
static void c_ThresholdReached(object? sender, ThresholdReachedEventArgs e)
{
Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}.");
Environment.Exit(0);
}
}
class CounterWithData(int passedThreshold)
{
private readonly int _threshold = passedThreshold;
private int _total;
public void Add(int x)
{
_total += x;
if (_total >= _threshold)
{
ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
args.Threshold = _threshold;
args.TimeReached = DateTime.Now;
OnThresholdReached(args);
}
}
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
ThresholdReached?.Invoke(this, e);
}
public event EventHandler<ThresholdReachedEventArgs>? ThresholdReached;
}
public class ThresholdReachedEventArgs : EventArgs
{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}
Module EventWithData
Sub Main()
Dim c As New CounterWithData(New Random().Next(10))
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
Console.WriteLine("press 'a' key to increase total")
While Console.ReadKey(True).KeyChar = "a"
Console.WriteLine("adding one")
c.Add(1)
End While
End Sub
Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs)
Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached)
Environment.Exit(0)
End Sub
End Module
Class CounterWithData
Private ReadOnly _threshold As Integer
Private _total As Integer
Public Sub New(passedThreshold As Integer)
_threshold = passedThreshold
End Sub
Public Sub Add(x As Integer)
_total += x
If (_total >= _threshold) Then
Dim args As New ThresholdReachedEventArgs With {
.Threshold = _threshold,
.TimeReached = Date.Now
}
OnThresholdReached(args)
End If
End Sub
Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs)
RaiseEvent ThresholdReached(Me, e)
End Sub
Public Event ThresholdReached As EventHandler(Of ThresholdReachedEventArgs)
End Class
Class ThresholdReachedEventArgs
Inherits EventArgs
Public Property Threshold As Integer
Public Property TimeReached As Date
End Class
Declare a custom delegate for an event
Declare a custom delegate only in rare scenarios, such as making your class available to legacy code that can't use generics. For most cases, use EventHandler<TEventArgs> as shown in the previous section.
Declare the custom delegate type.
The delegate signature must match the event handler signature—two parameters: the event source (
object; in Visual Basic,Object) and the event data class:public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)Declare the event using your custom delegate type instead of EventHandler<TEventArgs>:
public event ThresholdReachedEventHandler? ThresholdReached;Public Event ThresholdReached As ThresholdReachedEventHandlerAdd a
protected virtualmethod (Protected Overridablein Visual Basic) to raise the event.In C#, use the null-conditional operator (
?.) to guard against no subscribers (in Visual Basic,RaiseEventhandles this automatically):protected virtual void OnThresholdReached(ThresholdReachedEventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs) RaiseEvent ThresholdReached(Me, e) End SubPopulate the event data object and call the raise method when the condition is met:
if (_total >= _threshold) { ThresholdReachedEventArgs args = new(); args.Threshold = _threshold; args.TimeReached = DateTime.Now; OnThresholdReached(args); }If (_total >= _threshold) Then Dim args As New ThresholdReachedEventArgs With { .Threshold = _threshold, .TimeReached = Date.Now } OnThresholdReached(args) End IfSubscribe to the event using the
+=operator (in Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedDefine the event handler.
The handler signature must match the custom delegate—
objectfor the sender and your event data class for the second parameter:static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e) { Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}."); Environment.Exit(0); }Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs) Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached) Environment.Exit(0) End Sub
The following example shows the complete implementation:
class EventWithDelegate
{
static void Main()
{
CounterWithDelegate c = new(new Random().Next(10));
c.ThresholdReached += c_ThresholdReached;
Console.WriteLine("press 'a' key to increase total");
while (Console.ReadKey(true).KeyChar == 'a')
{
Console.WriteLine("adding one");
c.Add(1);
}
}
static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
{
Console.WriteLine($"The threshold of {e.Threshold} was reached at {e.TimeReached}.");
Environment.Exit(0);
}
}
class CounterWithDelegate(int passedThreshold)
{
private readonly int _threshold = passedThreshold;
private int _total;
public void Add(int x)
{
_total += x;
if (_total >= _threshold)
{
ThresholdReachedEventArgs args = new();
args.Threshold = _threshold;
args.TimeReached = DateTime.Now;
OnThresholdReached(args);
}
}
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
ThresholdReached?.Invoke(this, e);
}
public event ThresholdReachedEventHandler? ThresholdReached;
}
public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Module EventWithDelegate
Sub Main()
Dim c As New CounterWithDelegate(New Random().Next(10))
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
Console.WriteLine("press 'a' key to increase total")
While Console.ReadKey(True).KeyChar = "a"
Console.WriteLine("adding one")
c.Add(1)
End While
End Sub
Sub c_ThresholdReached(sender As Object, e As ThresholdReachedEventArgs)
Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached)
Environment.Exit(0)
End Sub
End Module
Class CounterWithDelegate
Private ReadOnly _threshold As Integer
Private _total As Integer
Public Sub New(passedThreshold As Integer)
_threshold = passedThreshold
End Sub
Public Sub Add(x As Integer)
_total += x
If (_total >= _threshold) Then
Dim args As New ThresholdReachedEventArgs With {
.Threshold = _threshold,
.TimeReached = Date.Now
}
OnThresholdReached(args)
End If
End Sub
Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs)
RaiseEvent ThresholdReached(Me, e)
End Sub
Public Event ThresholdReached As ThresholdReachedEventHandler
End Class
Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)