Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Wenn eine Klasse viele Ereignisse mithilfe von feldähnlichen Ereignisdeklarationen definiert, generiert der Compiler für jedes ereignisähnliche Feld ein Sicherungsfeld. Jede Instanz dieser Klasse weist Speicher für alle diese Felder zu – auch für Ereignisse, die nie abonniert werden. Bei vielen Ereignissen verschwendet dieser Pro-Instanz-Overhead Arbeitsspeicher.
Um diesen Arbeitsspeicheraufwand zu vermeiden, verwenden Sie Ereigniseigenschaften, die von einer Delegatenauflistung unterstützt werden. Die Auflistung muss Methoden bereitstellen, die Stellvertretungen nach Ereignisschlüssel festlegen, zugreifen und abrufen. EventHandlerList ist für diesen Zweck konzipiert, aber Sie können auch eine Hashtable oder eine Klasse verwenden, die von DictionaryBase abgeleitet ist. Halten Sie die Implementierungsdetails der Sammlung geheim.
Jede Ereigniseigenschaft definiert einen Add-Accessor und einen Remove-Accessor. Der Add-Accessor fügt der Delegatenauflistung den Eingabedelegat hinzu, und der Remove-Accessor entfernt ihn. Beide Accessoren verwenden einen vordefinierten Schlüssel, um Instanzen aus der Auflistung hinzuzufügen und daraus zu entfernen.
Voraussetzungen
Machen Sie sich mit den Konzepten im Artikel "Ereignisse " vertraut.
Definieren mehrerer Ereignisse mithilfe von Ereigniseigenschaften
Mit diesen Schritten wird eine Sensor Klasse erstellt, die 10 Ereigniseigenschaften verfügbar macht, die alle von einer einzelnen EventHandlerListKlasse unterstützt werden.
Definieren Sie eine Ereignisdatenklasse, die von EventArgs.
Fügen Sie Eigenschaften für jeden Datenabschnitt hinzu, den Sie an den Handler übergeben möchten:
public class SensorEventArgs(string sensorId, double value) : EventArgs { public string SensorId { get; } = sensorId; public double Value { get; } = value; }Public Class SensorEventArgs Inherits EventArgs Public ReadOnly Property SensorId As String Public ReadOnly Property Value As Double Public Sub New(sensorId As String, value As Double) Me.SensorId = sensorId Me.Value = value End Sub End ClassDeklarieren Sie ein EventHandlerList Feld zum Speichern der Stellvertretungen:
protected EventHandlerList listEventDelegates = new();Protected listEventDelegates As New EventHandlerList()Deklarieren Sie einen eindeutigen Schlüssel für jedes Ereignis.
EventHandlerListspeichert Delegierte anhand eines Schlüssels. Verwenden Sie einstatic readonlyObjekt (Shared ReadOnlyin Visual Basic) für jeden Schlüssel – die Objektidentität stellt sicher, dass jeder Schlüssel wirklich eindeutig ist:static readonly object temperatureChangedKey = new(); static readonly object humidityChangedKey = new(); static readonly object pressureChangedKey = new(); static readonly object batteryLowKey = new(); static readonly object signalLostKey = new(); static readonly object signalRestoredKey = new(); static readonly object thresholdExceededKey = new(); static readonly object calibrationRequiredKey = new(); static readonly object dataReceivedKey = new(); static readonly object errorDetectedKey = new();Shared ReadOnly temperatureChangedKey As New Object() Shared ReadOnly humidityChangedKey As New Object() Shared ReadOnly pressureChangedKey As New Object() Shared ReadOnly batteryLowKey As New Object() Shared ReadOnly signalLostKey As New Object() Shared ReadOnly signalRestoredKey As New Object() Shared ReadOnly thresholdExceededKey As New Object() Shared ReadOnly calibrationRequiredKey As New Object() Shared ReadOnly dataReceivedKey As New Object() Shared ReadOnly errorDetectedKey As New Object()Definieren Sie jedes Ereignis als Ereigniseigenschaft mit benutzerdefinierten Accessoren zum Hinzufügen und Entfernen.
Jeder Accessor ruft
AddHandleroderRemoveHandlerin der Liste mithilfe des Schlüssels dieses Ereignisses auf. Fügen Sie in C# auch eineprotected virtualraise-Methode hinzu, mit der der Delegat aus der Liste anhand des Schlüssels abgerufen und aufgerufen wird. In Visual Basic enthält dieCustom EventDeklaration bereits einenRaiseEventBlock, der dies tut:public event EventHandler<SensorEventArgs> TemperatureChanged { add { listEventDelegates.AddHandler(temperatureChangedKey, value); } remove { listEventDelegates.RemoveHandler(temperatureChangedKey, value); } } protected virtual void OnTemperatureChanged(SensorEventArgs e) => ((EventHandler<SensorEventArgs>?)listEventDelegates[temperatureChangedKey])?.Invoke(this, e);Public Custom Event TemperatureChanged As EventHandler(Of SensorEventArgs) AddHandler(Value As EventHandler(Of SensorEventArgs)) listEventDelegates.AddHandler(temperatureChangedKey, Value) End AddHandler RemoveHandler(Value As EventHandler(Of SensorEventArgs)) listEventDelegates.RemoveHandler(temperatureChangedKey, Value) End RemoveHandler RaiseEvent(sender As Object, e As SensorEventArgs) CType(listEventDelegates(temperatureChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e) End RaiseEvent End EventWiederholen Sie dieses Muster für jedes Ereignis unter Verwendung des entsprechenden Schlüssels.
Abonnieren des ereignisses mithilfe des
+=Operatoren (in Visual Basic,AddHandler):sensor.TemperatureChanged += Sensor_TemperatureChanged;AddHandler sensor.TemperatureChanged, AddressOf Sensor_TemperatureChangedDefinieren Sie den Ereignishandler.
Die Signatur muss mit dem EventHandler<TEventArgs> Delegaten übereinstimmen – ein
objectSender und Ihre Ereignisdatenklasse als zweiter Parameter:static void Sensor_TemperatureChanged(object? sender, SensorEventArgs e) => Console.WriteLine($"Sensor {e.SensorId}: temperature changed to {e.Value}.");Sub Sensor_TemperatureChanged(sender As Object, e As SensorEventArgs) Console.WriteLine("Sensor {0}: temperature changed to {1}.", e.SensorId, e.Value) End Sub
Das folgende Beispiel zeigt die vollständige Sensor Klassenimplementierung:
using System.ComponentModel;
public class SensorEventArgs(string sensorId, double value) : EventArgs
{
public string SensorId { get; } = sensorId;
public double Value { get; } = value;
}
// Sensor defines 10 event properties backed by a single EventHandlerList.
// EventHandlerList is memory-efficient for classes with many events: it only
// allocates storage for events that have active subscribers.
class Sensor
{
protected EventHandlerList listEventDelegates = new();
static readonly object temperatureChangedKey = new();
static readonly object humidityChangedKey = new();
static readonly object pressureChangedKey = new();
static readonly object batteryLowKey = new();
static readonly object signalLostKey = new();
static readonly object signalRestoredKey = new();
static readonly object thresholdExceededKey = new();
static readonly object calibrationRequiredKey = new();
static readonly object dataReceivedKey = new();
static readonly object errorDetectedKey = new();
public event EventHandler<SensorEventArgs> TemperatureChanged
{
add { listEventDelegates.AddHandler(temperatureChangedKey, value); }
remove { listEventDelegates.RemoveHandler(temperatureChangedKey, value); }
}
protected virtual void OnTemperatureChanged(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[temperatureChangedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> HumidityChanged
{
add { listEventDelegates.AddHandler(humidityChangedKey, value); }
remove { listEventDelegates.RemoveHandler(humidityChangedKey, value); }
}
protected virtual void OnHumidityChanged(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[humidityChangedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> PressureChanged
{
add { listEventDelegates.AddHandler(pressureChangedKey, value); }
remove { listEventDelegates.RemoveHandler(pressureChangedKey, value); }
}
protected virtual void OnPressureChanged(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[pressureChangedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> BatteryLow
{
add { listEventDelegates.AddHandler(batteryLowKey, value); }
remove { listEventDelegates.RemoveHandler(batteryLowKey, value); }
}
protected virtual void OnBatteryLow(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[batteryLowKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> SignalLost
{
add { listEventDelegates.AddHandler(signalLostKey, value); }
remove { listEventDelegates.RemoveHandler(signalLostKey, value); }
}
protected virtual void OnSignalLost(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[signalLostKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> SignalRestored
{
add { listEventDelegates.AddHandler(signalRestoredKey, value); }
remove { listEventDelegates.RemoveHandler(signalRestoredKey, value); }
}
protected virtual void OnSignalRestored(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[signalRestoredKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> ThresholdExceeded
{
add { listEventDelegates.AddHandler(thresholdExceededKey, value); }
remove { listEventDelegates.RemoveHandler(thresholdExceededKey, value); }
}
protected virtual void OnThresholdExceeded(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[thresholdExceededKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> CalibrationRequired
{
add { listEventDelegates.AddHandler(calibrationRequiredKey, value); }
remove { listEventDelegates.RemoveHandler(calibrationRequiredKey, value); }
}
protected virtual void OnCalibrationRequired(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[calibrationRequiredKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> DataReceived
{
add { listEventDelegates.AddHandler(dataReceivedKey, value); }
remove { listEventDelegates.RemoveHandler(dataReceivedKey, value); }
}
protected virtual void OnDataReceived(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[dataReceivedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> ErrorDetected
{
add { listEventDelegates.AddHandler(errorDetectedKey, value); }
remove { listEventDelegates.RemoveHandler(errorDetectedKey, value); }
}
protected virtual void OnErrorDetected(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[errorDetectedKey])?.Invoke(this, e);
}
Imports System.ComponentModel
Public Class SensorEventArgs
Inherits EventArgs
Public ReadOnly Property SensorId As String
Public ReadOnly Property Value As Double
Public Sub New(sensorId As String, value As Double)
Me.SensorId = sensorId
Me.Value = value
End Sub
End Class
' Sensor defines 10 event properties backed by a single EventHandlerList.
' EventHandlerList is memory-efficient for classes with many events: it only
' allocates storage for events that have active subscribers.
Class Sensor
Protected listEventDelegates As New EventHandlerList()
Shared ReadOnly temperatureChangedKey As New Object()
Shared ReadOnly humidityChangedKey As New Object()
Shared ReadOnly pressureChangedKey As New Object()
Shared ReadOnly batteryLowKey As New Object()
Shared ReadOnly signalLostKey As New Object()
Shared ReadOnly signalRestoredKey As New Object()
Shared ReadOnly thresholdExceededKey As New Object()
Shared ReadOnly calibrationRequiredKey As New Object()
Shared ReadOnly dataReceivedKey As New Object()
Shared ReadOnly errorDetectedKey As New Object()
Public Custom Event TemperatureChanged As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(temperatureChangedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(temperatureChangedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(temperatureChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event HumidityChanged As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(humidityChangedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(humidityChangedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(humidityChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event PressureChanged As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(pressureChangedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(pressureChangedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(pressureChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event BatteryLow As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(batteryLowKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(batteryLowKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(batteryLowKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event SignalLost As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(signalLostKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(signalLostKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(signalLostKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event SignalRestored As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(signalRestoredKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(signalRestoredKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(signalRestoredKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event ThresholdExceeded As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(thresholdExceededKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(thresholdExceededKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(thresholdExceededKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event CalibrationRequired As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(calibrationRequiredKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(calibrationRequiredKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(calibrationRequiredKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event DataReceived As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(dataReceivedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(dataReceivedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(dataReceivedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event ErrorDetected As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(errorDetectedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(errorDetectedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(errorDetectedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
End Class