如何:在类中实现事件

下面的过程说明如何在类中实现事件。 第一个过程实现没有关联数据的事件,它将 System.EventArgs 类和 System.EventHandler 类用作事件数据和委托处理程序。 第二个过程实现具有自定义数据的事件,它为事件数据和事件委托处理程序定义自定义类。

注意注意

本主题演示如何声明和引发类中的事件。不演示如何定义使用该事件的事件处理程序。有关如何使用事件的信息,请参见使用事件如何:引发和使用事件

有关阐释引发和处理事件的完整示例,请参见如何:引发和使用事件

实现不具有事件特定的数据的事件

  1. 在类中定义公共事件成员。 将事件成员的类型设置为 System.EventHandler 委托。

    Public Class Countdown
        ' ...
    
        Public Event CountdownCompleted As EventHandler
    End Class
    
    public class Countdown 
    {
        // ...
    
        public event EventHandler CountdownCompleted;   
    }
    
  2. 在引发事件的类中提供一个受保护的方法。 对 OnEventName 方法进行命名。 在该方法中引发该事件。 请注意,应检查 C# 代码来确定引发事件前事件是否为空。 这样就无需处理引发事件但没有附加的事件处理程序时引发的 NullReferenceException。 在本例中进行这种检查很有必要,因为 CountDown 类只引发事件,而不为其提供处理程序。

    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. 在类中确定引发该事件的时间。 调用 OnEventName 以引发该事件。

    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());
       }
    }
    

实现具有事件特定的数据的事件

  1. 定义一个提供事件数据的类。 对类 EventNameArgs 进行命名,从 System.EventArgs 派生该类,然后添加所有事件特定的成员。

    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. 声明事件的委托。 对委托 EventNameEventHandler 进行命名。

    Public Delegate Sub AlarmEventHandler(sender As Object, e As AlarmEventArgs)
    
    public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
    
  3. 在类中定义名为 EventName 的公共事件成员。 将事件成员的类型设置为事件委托类型。

    Public Class AlarmClock
        ' ...
        Public Event Alarm As AlarmEventHandler
    
    End Class
    
    public class AlarmClock 
    {
        // ...
        public event AlarmEventHandler Alarm;
    
    }
    
  4. 在引发事件的类中定义一个受保护的方法。 对 OnEventName 方法进行命名。 在该方法中引发该事件。 请注意,应检查 C# 代码来确定引发事件前事件是否为空。 这样就无需处理引发事件但没有附加的事件处理程序时引发的 NullReferenceException。 在本例中进行这种检查很有必要,因为 CountDown 类只引发事件,而不为其提供处理程序。

    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. 在类中确定引发该事件的时间。 调用 OnEventName 以引发该事件并使用 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); 
        }
    }
    

示例

下面的示例定义 DiskSpaceMonitor 类,只要可用磁盘空间低于配置文件中定义的百分比,该类就使用事件生成警告。 它还定义 DiskSpaceWarningEventArgs 类来为事件处理程序提供可用磁盘空间上的自定义数据。

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);
   }   
}

此示例定义名为 DiskSpaceWarningEventArgs 的自定义事件数据类,而不使用 EventArgs 类提供事件数据。 它提供带有驱动器名称的事件处理程序,以及驱动器上的可用空间量和总空间量。 此示例还定义表示事件签名的委托 DiskSpaceWarningEventHandler。

DiskSpaceMonitor 类定义 DiskSpaceWarning 事件,还提供引发该事件的 OnDiskSpaceWarning 方法。 如果检测到驱动器上的可用空间少于或等于配置文件中定义的百分比,则 OnDiskSpaceWarning 方法将由 CheckFreeSpace 方法调用。

请参见

任务

如何:引发和使用事件

概念

事件和委托

引发事件

其他资源

处理和引发事件