Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule pokazano, jak pracować ze zdarzeniami w .NET za pomocą delegata EventHandler, delegata EventHandler<TEventArgs> oraz delegata niestandardowego, wraz z przykładami zdarzeń z danymi i bez danych.
Wymagania wstępne
Zapoznaj się z pojęciami w artykule Zdarzenia .
Zgłaszanie zdarzenia bez danych
Te kroki tworzą klasę Counter , która uruchamia ThresholdReached zdarzenie, gdy suma bieżąca osiągnie lub przekroczy próg.
Zadeklaruj zdarzenie przy użyciu delegata EventHandler .
Użyj
EventHandler, gdy zdarzenie nie przekazuje danych do obsługi:public event EventHandler? ThresholdReached;Public Event ThresholdReached As EventHandlerDodaj metodę
protected virtual(Protected Overridablew Visual Basic), aby zgłosić zdarzenie.Ten wzorzec pozwala klasom pochodnym zastąpić zachowanie podnoszenia zdarzeń bez bezpośredniego wywoływania delegata. W języku C#użyj operatora warunkowego o wartości null (
?.), aby chronić się przed żadnymi subskrybentami (w Visual BasicRaiseEventobsługuje to automatycznie):protected virtual void OnThresholdReached(EventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As EventArgs) RaiseEvent ThresholdReached(Me, e) End SubWywołaj metodę "raise" po spełnieniu warunku.
Przekaż Empty, ponieważ to zdarzenie nie niesie żadnych danych.
if (_total >= _threshold) { OnThresholdReached(EventArgs.Empty); }If (_total >= _threshold) Then OnThresholdReached(EventArgs.Empty) End IfSubskrybowanie zdarzenia przy użyciu
+=operatora (w Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedZdefiniuj metodę obsługi zdarzeń.
Jego podpis musi być zgodny z delegatem EventHandler — pierwszy parametr to źródło zdarzenia, a drugi to 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
W poniższym przykładzie przedstawiono kompletną implementację:
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
Zgłaszanie zdarzenia przy użyciu danych
Te kroki rozszerzają poprzedni Counter przykład, aby wywołać zdarzenie zawierające dane — wartość progową oraz czas, w którym została osiągnięta.
Zdefiniuj klasę danych zdarzeń dziedziczącą z EventArgs klasy.
Dodaj właściwości dla każdego elementu danych, które chcesz przekazać do programu obsługi:
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 ClassZadeklaruj zdarzenie przy użyciu delegata EventHandler<TEventArgs> , przekazując klasę danych zdarzenia jako argument typu:
public event EventHandler<ThresholdReachedEventArgs>? ThresholdReached;Public Event ThresholdReached As EventHandler(Of ThresholdReachedEventArgs)Dodaj metodę
protected virtual(Protected Overridablew Visual Basic), aby zgłosić zdarzenie.Ten wzorzec pozwala klasom pochodnym zastąpić zachowanie podnoszenia zdarzeń bez bezpośredniego wywoływania delegata. W języku C#użyj operatora warunkowego o wartości null (
?.), aby chronić się przed żadnymi subskrybentami (w Visual BasicRaiseEventobsługuje to automatycznie):protected virtual void OnThresholdReached(ThresholdReachedEventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs) RaiseEvent ThresholdReached(Me, e) End SubWypełnij obiekt danych zdarzenia i wywołaj metodę raise po spełnieniu warunku:
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 IfSubskrybowanie zdarzenia przy użyciu
+=operatora (w Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedZdefiniuj procedurę obsługi zdarzeń.
Drugi typ parametru to
ThresholdReachedEventArgszamiast EventArgs, co umożliwia programowi obsługi odczytywanie danych zdarzenia.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
W poniższym przykładzie przedstawiono kompletną implementację:
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
Zadeklaruj niestandardowego delegata dla zdarzenia
Delegata niestandardowego deklaruj tylko w rzadkich przypadkach, na przykład gdy chcesz udostępnić swoją klasę starszemu kodowi, który nie może używać typów ogólnych. W większości przypadków użyj polecenia EventHandler<TEventArgs> , jak pokazano w poprzedniej sekcji.
Zadeklaruj niestandardowy typ delegata.
Sygnatura delegata musi być zgodna z podpisem procedury obsługi zdarzeń — dwoma parametrami: źródłem zdarzeń (
object; w Visual BasicObject) i klasą danych zdarzenia:public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)Zadeklaruj zdarzenie przy użyciu niestandardowego typu delegata zamiast EventHandler<TEventArgs>:
public event ThresholdReachedEventHandler? ThresholdReached;Public Event ThresholdReached As ThresholdReachedEventHandlerDodaj metodę
protected virtual(Protected Overridablew Visual Basic), aby zgłosić zdarzenie.W języku C#użyj operatora warunkowego o wartości null (
?.), aby chronić się przed żadnymi subskrybentami (w Visual BasicRaiseEventobsługuje to automatycznie):protected virtual void OnThresholdReached(ThresholdReachedEventArgs e) { ThresholdReached?.Invoke(this, e); }Protected Overridable Sub OnThresholdReached(e As ThresholdReachedEventArgs) RaiseEvent ThresholdReached(Me, e) End SubWypełnij obiekt danych zdarzenia i wywołaj metodę raise po spełnieniu warunku:
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 IfSubskrybowanie zdarzenia przy użyciu
+=operatora (w Visual Basic,AddHandler):c.ThresholdReached += c_ThresholdReached;AddHandler c.ThresholdReached, AddressOf c_ThresholdReachedZdefiniuj procedurę obsługi zdarzeń.
Sygnatura programu obsługi musi być zgodna z niestandardowym delegatem —
objectdla nadawcy i klasy danych zdarzenia dla drugiego parametru: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
W poniższym przykładzie przedstawiono kompletną implementację:
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)