Share via


HOW TO:在您的類別中實作事件

下列程序說明如何在類別中實作事件: 第一個程序會實作沒有關聯資料的事件,它使用 System.EventArgsSystem.EventHandler 類別做為事件資料和委派處理常式。 第二個程序會實作具有自訂資料的事件,它會定義自訂類別做為事件資料和事件委派處理常式。

注意事項注意事項

本主題顯示如何在類別中宣告和引發事件。其中並不會顯示如何定義使用該事件的事件處理常式。如需如何使用事件的詳細資訊,請參閱使用事件HOW TO:引發和使用事件

如需示範引發和處理事件的完整範例,請參閱 HOW TO:引發和使用事件

若要實作不含事件特定資料的事件

  1. 在類別中定義公用事件成員。 將此事件成員的型別設定為 System.EventHandler 委派。

    Public Class Countdown
        ' ...
    
        Public Event CountdownCompleted As EventHandler
    End Class
    
    public class Countdown 
    {
        // ...
    
        public event EventHandler CountdownCompleted;   
    }
    
  2. 在引發事件的類別中提供一個保護的方法。 將此方法命名為 OnEventName。 在方法內引發此事件。 請注意,C# 程式碼在引發事件之前,應該先檢查事件是否為 null。 這樣可以避免因為引發未附加任何事件處理常式的事件,而必須處理擲回的 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# 程式碼在引發事件之前,應該先檢查事件是否為 null。 這樣可以避免因為引發未附加任何事件處理常式的事件,而必須處理擲回的 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);
   }   
}

範例中不會使用 EventArgs 類別來提供事件資料,而是定義名為 DiskSpaceWarningEventArgs 的自訂事件資料類別。 這個類別會提供磁碟機名稱及磁碟機的可用空間量和總空間量給事件處理常式。 範例中也定義表示事件簽章的委派 DiskSpaceWarningEventHandler。

DiskSpaceMonitor 類別會定義 DiskSpaceWarning 事件,並同時提供引發這個事件的 OnDiskSpaceWarning 方法。 當 CheckFreeSpace 方法在偵測到磁碟機的可用空間少於或等於組態檔中所定義的百分比時,就會呼叫 OnDiskSpaceWarning 方法。

請參閱

工作

HOW TO:引發和使用事件

概念

事件和委派

引發事件

其他資源

處理和引發事件