Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье показано, как работать с событиями в .NET с помощью делегата EventHandler , делегата EventHandler<TEventArgs> и пользовательского делегата с примерами событий с данными и без них.
Необходимые условия
Ознакомьтесь с понятиями в статье "События ".
Вызов события без данных
В этих шагах создается Counter класс, который инициирует ThresholdReached событие, когда текущая сумма достигает или превышает порог.
Объявите событие с помощью делегата EventHandler .
Используйте
EventHandler, когда событие не передает данные обработчику:public event EventHandler? ThresholdReached;Public Event ThresholdReached As EventHandlerprotected virtualДобавьте метод (Protected Overridableв Visual Basic), чтобы вызвать событие.Этот шаблон позволяет производным классам переопределять поведение создания событий без прямого вызова делегата. В C#, используйте оператор null-условия (
?.) для защиты от отсутствия подписчиков (в Visual Basic,RaiseEventобрабатывается автоматически):protected virtual void OnThresholdReached(EventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As EventArgs) RaiseEvent ThresholdReached(Me, e) End SubВызовите метод raise при выполнении условия.
Передайте Empty, так как это событие не содержит данных.
if (_total >= _threshold) { OnThresholdReached(EventArgs.Empty); }If (_total >= _threshold) Then OnThresholdReached(EventArgs.Empty) End IfПодпишитесь на событие с помощью
+=оператора (в Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedОпределите метод обработчика событий.
Его подпись должна соответствовать делегату EventHandler — первый параметр является источником событий, а второй — 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
В следующем примере показана полная реализация:
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
Инициировать событие с данными
Эти действия расширяют предыдущий Counter пример, чтобы вызвать событие, включающее данные — пороговое значение и время его достижения.
Определение класса данных событий, наследуемого от EventArgs.
Добавьте свойства для каждого фрагмента данных, которые необходимо передать обработчику:
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 ClassОбъявите событие с помощью делегата EventHandler<TEventArgs> , передав класс данных события в качестве аргумента типа:
public event EventHandler<ThresholdReachedEventArgs>? ThresholdReached;Public Event ThresholdReached As EventHandler(Of ThresholdReachedEventArgs)protected virtualДобавьте метод (Protected Overridableв Visual Basic), чтобы вызвать событие.Этот шаблон позволяет производным классам переопределять поведение создания событий без прямого вызова делегата. В C# используйте оператор null-условного (
?.) для защиты от отсутствия подписчиков (в Visual Basic операторRaiseEvent, он обрабатывается автоматически):protected virtual void OnThresholdReached(ThresholdReachedEventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs) RaiseEvent ThresholdReached(Me, e) End SubЗаполните объект данных события и вызовите метод raise при выполнении условия.
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 IfПодпишитесь на событие с помощью
+=оператора (в Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedОпределите обработчик событий.
Тип второго параметра — это
ThresholdReachedEventArgsвместо EventArgs, что позволяет обработчику считывать данные события: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
В следующем примере показана полная реализация:
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
Объявление пользовательского делегата для события
Объявляйте пользовательский делегат только в редких сценариях, например, чтобы сделать ваш класс доступным для устаревшего кода, который не может использовать дженерики. В большинстве случаев используйте EventHandler<TEventArgs> , как показано в предыдущем разделе.
Объявите пользовательский тип делегата.
Подпись делегата должна соответствовать сигнатуре обработчика событий — двумя параметрами: источником событий (
object; в Visual Basic)Objectи классом данных событий:public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)Объявите событие с помощью пользовательского типа делегата, а не EventHandler<TEventArgs>:
public event ThresholdReachedEventHandler? ThresholdReached;Public Event ThresholdReached As ThresholdReachedEventHandlerprotected virtualДобавьте метод (Protected Overridableв Visual Basic), чтобы вызвать событие.В C# используйте оператор null-условия (
?.) для защиты от отсутствия подписчиков (в Visual Basic,RaiseEventон обрабатывается автоматически):protected virtual void OnThresholdReached(ThresholdReachedEventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs) RaiseEvent ThresholdReached(Me, e) End SubЗаполните объект данных события и вызовите метод формирования события, когда условие выполнено.
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 IfПодпишитесь на событие с помощью
+=оператора (в Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedОпределите обработчик событий.
Подпись обработчика должна соответствовать пользовательскому делегату:
objectдля отправителя и вашему классу данных события для второго параметра.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
В следующем примере показана полная реализация:
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)