Gewusst wie: Implementieren von Ereignissen in der Klasse

Die folgenden Verfahren beschreiben, wie ein Ereignis in einer Klasse implementiert wird. Das erste Verfahren implementiert ein Ereignis, das über keine zugeordneten Daten verfügt. Es verwendet die System.EventArgs-Klasse und die System.EventHandler-Klasse für die Ereignisdaten und den Delegathandler. Das zweite Verfahren implementiert ein Ereignis mit benutzerdefinierten Daten und definiert benutzerdefinierte Klassen für die Ereignisdaten und den Ereignisdelegathandler.

Hinweis

In diesem Thema wird gezeigt, wie ein Ereignis in einer Klasse deklariert und ausgelöst wird.Das Definieren eines Ereignishandlers, der dieses Ereignis nutzt, wird nicht gezeigt.Weitere Informationen zur Verarbeitung von Ereignissen finden Sie unter Behandeln von Ereignissen und unter Gewusst wie: Auslösen und Behandeln von Ereignissen.

Ein vollständiges Beispiel, in dem das Auslösen und Behandeln von Ereignissen veranschaulicht wird, finden Sie unter Gewusst wie: Auslösen und Behandeln von Ereignissen.

So implementieren Sie ein Ereignis ohne ereignisspezifische Daten

  1. Definieren Sie in der Klasse einen öffentlichen Ereignismember. Legen Sie den Typ des Ereignismembers auf einen System.EventHandler-Delegat fest.

    Public Class Countdown
        ' ...
    
        Public Event CountdownCompleted As EventHandler
    End Class
    
    public class Countdown 
    {
        // ...
    
        public event EventHandler CountdownCompleted;   
    }
    
  2. Stellen Sie eine geschützte Methode in der Klasse bereit, die das Ereignis auslöst. Nennen Sie die Methode OnEventName. Lösen Sie das Ereignis innerhalb der Methode aus. Beachten Sie, dass vom C#-Code geprüft werden sollte, ob das Ereignis NULL ist, bevor das Ereignis ausgelöst wird. Dadurch muss keine Ausnahmebehandlung für die NullReferenceException durchgeführt werden, die ausgelöst wird, wenn ein Ereignis ohne Ereignishandler ausgelöst wird. Diese Überprüfung ist im gegebenen Fall notwendig, da die CountDown-Klasse nur das Ereignis auslöst, jedoch keinen entsprechenden Handler bereitstellt.

    Public Class Countdown
       ' ...
    
       Public Event CountdownCompleted As EventHandler
    
       Protected Overridable Sub OnCountdownCompleted(e As EventArgs)
          RaiseEvent CountdownCompleted(Me, e)
       End Sub
    End Class
    
    public class Countdown 
    {
        public event EventHandler CountdownCompleted;   
    
        protected virtual void OnCountdownCompleted(EventArgs e)
        {
            if (CountdownCompleted != null)
                CountdownCompleted(this, e);
        }
    }
    
  3. Bestimmen Sie, wann das Ereignis in der Klasse ausgelöst werden soll. Rufen Sie OnEventName auf, um das Ereignis auszulösen.

    Public Class Countdown
       Dim internalCounter As Integer = 0
        ' ...
    
       Public Event CountdownCompleted As EventHandler
    
       Protected Overridable Sub OnCountdownCompleted(e As EventArgs)
          RaiseEvent CountdownCompleted(Me, e)
       End Sub
    
       Public Sub Decrement()
          internalCounter -= 1
          If internalCounter = 0
             OnCountdownCompleted(New EventArgs())
          End If
       End Sub
    End Class
    
    public class Countdown 
    {
       int internalCounter = 0;
       // ...
    
       public event EventHandler CountdownCompleted;   
    
        protected virtual void OnCountdownCompleted(EventArgs e)
        {
            if (CountdownCompleted != null)
                CountdownCompleted(this, e);
        }
    
       public void Decrement()
       {
          internalCounter--;
          if (internalCounter == 0)
             OnCountdownCompleted(new EventArgs());
       }
    }
    

So implementieren Sie ein Ereignis mit ereignisspezifischen Daten

  1. Definieren Sie eine Klasse, die Daten für das Ereignis bereitstellt. Nennen Sie die Klasse EventNameArgs, leiten Sie die Klasse von System.EventArgs ab, und fügen Sie alle ereignisspezifischen Member hinzu.

    Public Class AlarmEventArgs : Inherits EventArgs
       Private nRings As Integer = 0
       Private pressed As Boolean = False
       Private text As String = "The alarm is ringing!"
    
       ' Constructor.
       Public Sub New(ByVal snoozePressed As Boolean, ByVal nRings As Integer) 
          Me.pressed = snoozePressed
          Me.nRings = nRings
       End Sub
    
       ' Properties.
       Public Property AlarmText() As String
          Get
             Return Me.text
          End Get
          Set
             Me.text = value
          End Set  
       End Property 
    
       Public ReadOnly Property NumRings() As Integer
          Get
             Return Me.nRings
          End Get   
       End Property 
    
       Public ReadOnly Property SnoozePressed() As Boolean
          Get
             Return Me.pressed
          End Get
       End Property
    End Class
    
    public class AlarmEventArgs : EventArgs 
    {
       private readonly int nRings = 0;
       private readonly bool pressed = false;
       private string text = "The alarm is ringing!";
    
       // Constructor.
       public AlarmEventArgs(bool snoozePressed, int nRings) 
       {
          this.pressed = snoozePressed;
          this.nRings = nRings;
       }
    
       // Properties.
       public string AlarmText {  
          get { return text; }
          set { this.text = value; }
       }
    
       public int NumRings {
          get { return nRings; }
       }
    
       public bool SnoozePressed {
          get { return pressed; }
       }
    }
    
  2. Deklarieren Sie einen Delegat für das Ereignis. Nennen Sie den Delegat EventNameEventHandler.

    Public Delegate Sub AlarmEventHandler(sender As Object, e As AlarmEventArgs)
    
    public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
    
  3. Definieren Sie in der Klasse einen öffentlichen Ereignismember mit dem Namen EventName. Legen Sie den Typ des Ereignismembers auf den Ereignisdelegattyp fest.

    Public Class AlarmClock
        ' ...
        Public Event Alarm As AlarmEventHandler
    
    End Class
    
    public class AlarmClock 
    {
        // ...
        public event AlarmEventHandler Alarm;
    
    }
    
  4. Definieren Sie eine geschützte Methode in der Klasse, die das Ereignis auslöst. Nennen Sie die Methode OnEventName. Lösen Sie das Ereignis innerhalb der Methode aus. Beachten Sie, dass vom C#-Code geprüft werden sollte, ob das Ereignis NULL ist, bevor das Ereignis ausgelöst wird. Dadurch muss keine Ausnahmebehandlung für die NullReferenceException durchgeführt werden, die ausgelöst wird, wenn ein Ereignis ohne Ereignishandler ausgelöst wird. Diese Überprüfung ist im gegebenen Fall notwendig, da die CountDown-Klasse nur das Ereignis auslöst, jedoch keinen entsprechenden Handler bereitstellt.

    Public Class AlarmClock
    
        ' ...
        Public Event Alarm As AlarmEventHandler
    
        Protected Overridable Sub OnAlarm(e As AlarmEventArgs)
            RaiseEvent Alarm(Me, e)
        End Sub
    End Class
    
    public class AlarmClock 
    {
        // ...
        public event AlarmEventHandler Alarm;
    
        protected virtual void OnAlarm(AlarmEventArgs e)
        {
          if (Alarm != null) 
              Alarm(this, e); 
        }
    }
    
  5. Bestimmen Sie, wann das Ereignis in der Klasse ausgelöst werden soll. Rufen Sie OnEventName auf, um das Ereignis auszulösen, und übergeben Sie die ereignisspezifischen Daten mit EventNameEventArgs.

    Public Class AlarmClock
    
        Public Sub Start
            ' ...
            System.Threading.Thread.Sleep(300)
            Dim e As AlarmEventArgs = New AlarmEventArgs(False, 0)
            OnAlarm(e)
        End Sub
    
        Public Event Alarm As AlarmEventHandler
    
        Protected Overridable Sub OnAlarm(e As AlarmEventArgs)
            RaiseEvent Alarm(Me, e)
        End Sub
    End Class
    
    public class AlarmClock 
    {
        public void Start()
        {
            // ...
            System.Threading.Thread.Sleep(300);
            AlarmEventArgs e = new AlarmEventArgs(false, 0);
            OnAlarm(e);
        }
    
        public event AlarmEventHandler Alarm;
    
        protected virtual void OnAlarm(AlarmEventArgs e)
        {
          if (Alarm != null) 
              Alarm(this, e); 
        }
    }
    

Beispiel

Im folgenden Beispiel wird eine DiskSpaceMonitor-Klasse definiert, die ein Ereignis verwendet, um eine Warnung zu erzeugen, wenn der freie Speicherplatz unter einen Prozentsatz sinkt, der in einer Konfigurationsdatei festgelegt wurde. Außerdem wird eine DiskSpaceWarningEventArgs-Klasse definiert, um benutzerdefinierte Daten in freiem Festplattenspeicher für Ereignishandler bereitzustellen.

Imports System.Collections.Specialized
Imports System.Configuration
Imports System.IO

Public Class DiskSpaceWarningEventArgs : Inherits EventArgs
   Dim currentFreeSpace As Long
   Dim currentTotalSpace As Long
   Dim driveName As String

   Public Sub New(name As String, freeSpace As Long, totalSpace As Long)
      Me.driveName = name
      Me.currentFreeSpace = freeSpace
      Me.currentTotalSpace = totalSpace
   End Sub

   Public ReadOnly Property Name As String
      Get
         Return Me.driveName
      End Get
   End Property

   Public ReadOnly Property FreeSpace As Long
      Get
         Return Me.currentFreeSpace 
      End Get
   End Property

   Public ReadOnly Property TotalSpace As Long
      Get
         Return Me.currentTotalSpace
      End Get
   End Property
End Class

Public Delegate Sub DiskSpaceWarningEventHandler(sender As Object, _
                                                 e As DiskSpaceWarningEventArgs)

Public Class DiskSpaceMonitor
   Public Event DiskSpaceWarning As DiskSpaceWarningEventHandler
   Private threshhold As Decimal 

   Public Sub New()
      ' Retrieve threshhold to fire event from configuration file.
      Try
         Dim settings As NameValueCollection = ConfigurationManager.AppSettings
         Me.threshhold = CDec(settings.Item("Threshhold"))
      ' If there is no configuration file, provide a default value.
      Catch e As ConfigurationErrorsException
         Me.threshhold = 10d
      Catch e As InvalidCastException
         Me.threshhold = 10d
      End Try               
   End Sub

   Public Sub CheckFreeSpace
      ' Get drives present on system.
      Dim drives() As DriveInfo = DriveInfo.GetDrives()
      For Each drive As DriveInfo In drives
         If drive.IsReady Then
            If drive.TotalFreeSpace/drive.TotalSize <= Me.threshhold Then
               OnDiskSpaceWarning(New DiskSpaceWarningEventArgs(drive.Name, _
                                  drive.TotalFreeSpace, drive.TotalSize))
            End If
         End If
      Next   
   End Sub

   Protected Sub OnDiskSpaceWarning(e As DiskSpaceWarningEventArgs)
      RaiseEvent DiskSpaceWarning(me, e)
   End Sub
End Class
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;

public class DiskSpaceWarningEventArgs : EventArgs
{
   private long currentFreeSpace;
   private long currentTotalSpace;
   private string driveName;

   public DiskSpaceWarningEventArgs(string name, long freeSpace, long totalSpace)
   {
      this.driveName = name;
      this.currentFreeSpace = freeSpace;
      this.currentTotalSpace = totalSpace;
   }

   public string Name
   {
      get { return this.driveName; }
   }

   public long FreeSpace
   {
      get { return this.currentFreeSpace; }
   }

   public long TotalSpace
   {
      get { return this.currentTotalSpace; }
   }
}

public delegate void DiskSpaceWarningEventHandler(object sender, 
                                                  DiskSpaceWarningEventArgs e);

public class DiskSpaceMonitor
{
   public event DiskSpaceWarningEventHandler DiskSpaceWarning;
   private decimal threshhold;

   public DiskSpaceMonitor()
   {
      // Retrieve threshhold to fire event from configuration file.
      try
      {
         NameValueCollection settings = ConfigurationManager.AppSettings;
         this.threshhold = Convert.ToDecimal(settings["Threshhold"]);
      }
      // If there is no configuration file, provide a default value.
      catch (ConfigurationErrorsException)
      {
         this.threshhold = 10m;
      }
      catch (InvalidCastException)
      {
         this.threshhold = 10m;
      }
   }

   public void CheckFreeSpace()
   {
      // Get drives present on system.
      DriveInfo[] drives = DriveInfo.GetDrives();
      foreach (DriveInfo drive in drives)
      {
         if (drive.IsReady)
         {
            if (drive.TotalFreeSpace/drive.TotalSize <= this.threshhold)
               OnDiskSpaceWarning(new DiskSpaceWarningEventArgs(drive.Name, 
                                  drive.TotalFreeSpace, drive.TotalSize));
         }
      }
   }

   protected void OnDiskSpaceWarning(DiskSpaceWarningEventArgs e)
   {
      if (DiskSpaceWarning != null)
         DiskSpaceWarning(this, e);
   }   
}

Im Beispiel wird die benutzerdefinierte Ereignisdatenklasse DiskSpaceWarningEventArgs definiert, anstatt Ereignisdaten mithilfe der EventArgs-Klasse bereitzustellen. Für Ereignishandler wird der Laufwerkname bereitgestellt, und der freie Speicherplatz sowie der gesamte verfügbare Speicherplatz auf dem Datenträger werden angegeben. Außerdem wird im Beispiel der DiskSpaceWarningEventHandler-Delegat definiert, der die Ereignissignatur darstellt.

Die DiskSpaceMonitor-Klasse definiert das DiskSpaceWarning-Ereignis und stellt eine OnDiskSpaceWarning-Methode bereit, die das Ereignis auslöst. Sobald festgestellt wurde, dass der freie Speicherplatz auf einem Laufwerk kleiner oder gleich einem Prozentsatz ist, der in einer Konfigurationsdatei definiert wurde, wird die OnDiskSpaceWarning-Methode von der CheckFreeSpace-Methode aufgerufen.

Siehe auch

Aufgaben

Gewusst wie: Auslösen und Behandeln von Ereignissen

Konzepte

Ereignisse und Delegaten

Auslösen eines Ereignisses

Weitere Ressourcen

Behandeln und Auslösen von Ereignissen