イベントの使用方法のガイドライン

次の規則は、イベントの使用方法のガイドラインを示しています。

  • 推奨されるイベントの名前付けのガイドラインに基づいて、イベント名を選択します。

  • ドキュメントでイベントについて記述する場合は、"イベントの起動 (fire)" または "イベントのトリガ (trigger)" ではなく、"イベントの発生 (raise)" と表現します。

  • void キーワードをサポートする言語では、次の C# のコード例で示すように、イベント ハンドラの戻り値の型として void を使用します。

    public delegate void MouseEventHandler(object sender, MouseEventArgs e);
    
  • イベントによりマウス クリックの座標などの意味のあるデータを伝達する場合は、厳密に型を指定したイベント データ クラスを使用します。

  • イベント クラスは、次の例で示すように、System.EventArgs クラスを拡張したクラスにする必要があります。

    Public Class MouseEventArgs
       Inherits EventArgs 
       ' Code for the class goes here.
    End Class
    [C#]
    public class MouseEvent: EventArgs {}
    
  • 各イベントを発生させるには、protected (Visual Basic の場合は Protected ) 仮想メソッドを使用します。シール クラスからはクラスを派生できないため、この手法はシール クラスには適しません。このメソッドの目的は、派生クラスでオーバーライドを使用してイベントを処理できるようにすることです。開発者が派生クラスを作成する場合には、デリゲートよりもこのメソッドを使用した方が自然です。メソッド名は、OnEventName (EventName は発生させるイベントの名前) という形式で付けます。次に例を示します。

    Public Class Button
       Private onClickHandler As ButtonClickHandler  
       Protected Overridable Sub OnClick(e As ClickEventArgs)
          ' Call the delegate if non-null.
          If Not (onClickHandler Is Nothing) Then
             onClickHandler(Me, e)
          End If 
       End Sub
    End Class
    
    [C#]
    public class Button 
    {
       ButtonClickHandler onClickHandler;
    
       protected virtual void OnClick(ClickEventArgs e) 
       {
          // Call the delegate if non-null.
          if (onClickHandler != null)
                onClickHandler(this, e);      
       }
    }
    

    派生クラスでは、OnEventName を処理するときに基本クラスを呼び出さないようにすることもできます。その場合は、基本クラスが正常に動作するために必要な処理を OnEventName メソッドには含めないようにします。

  • イベント ハンドラには、あらゆるコードが含まれるということを前提とする必要があります。クラスは、イベント ハンドラがあらゆる操作を実行した場合に備えておく必要があり、イベントが発生した後には、該当するオブジェクトが必ず適切な状態になるようにします。コード内のイベントが発生する位置では、try/finally ブロックを使用するようにしてください。開発者が別のアクションを実行するためにオブジェクトに対してコールバック関数を実行する場合があるため、イベントが発生した位置に制御が戻されたときのオブジェクトの状態については、何も前提とはしないでください。次に例を示します。

    Public Class Button
       Private onClickHandler As ButtonClickHandler
       Protected Sub DoClick()
          ' Paint button in indented state.      
          PaintDown()
          Try
             ' Call event handler.
             OnClick()      
          Finally
             ' Window might be deleted in event handler.
             If Not (windowHandle Is Nothing) Then
                ' Paint button in normal state.
                PaintUp()
             End If 
          End Try
       End Sub
       Protected Overridable Sub OnClick(e As ClickEvent)
          If Not (onClickHandler Is Nothing) Then
             onClickHandler(Me, e)
          End If
       End Sub
    End Class
    [C#]
    public class Button
    {
       ButtonClickHandler onClickHandler;
    
       protected void DoClick()
       {
          // Paint button in indented state.
          PaintDown();
             try
          {
             // Call event handler.
             OnClick();         
          }
          finally
          {
             // Window might be deleted in event handler.
             if (windowHandle != null)
                // Paint button in normal state.
                PaintUp();            
          }
       }
    
       protected virtual void OnClick(ClickEvent e)
       {
          if (onClickHandler != null)
             onClickHandler(this, e);
       }
    }
    
  • 開発者がオブジェクトのイベントを制御できるように、System.ComponentModel.CancelEventArgs クラスを使用または拡張します。たとえば、ユーザーがノード ラベルを編集しようとすると、TreeView コントロールにより BeforeLabelEdit が発生します。開発者がこのイベントを使用して、ノードを編集できないようにする方法を次のコード例に示します。

    Public Class Form1
       Inherits Form
       Private treeView1 As New TreeView() 
    
       Sub treeView1_BeforeLabelEdit(source As Object, e As NodeLabelEditEventArgs)
          e.CancelEdit = True
       End Sub
    End Class
    [C#]
    public class Form1: Form 
    {
       TreeView treeView1 = new TreeView();
    
       void treeView1_BeforeLabelEdit(object source, 
          NodeLabelEditEventArgs e) 
       {
          e.CancelEdit = true;
       }
    }
    

    この例では、エラーは生成されません。ラベルが読み取り専用になります。

    操作をキャンセルして例外を返す場合には、この Cancel イベントは適切ではありません。これらのケースでは、操作をキャンセルするには、イベント ハンドラ内で例外を発生させます。たとえば、エディット コントロールで検証ロジックを記述するには、次のようにします。

    Public Class Form1
       Inherits Form
       Private edit1 As EditBox = New EditBox() 
    
       Sub TextChanging(source As Object, e As EventArgs)
          Throw New RuntimeException("Invalid edit")
       End Sub
    End Class
    [C#]
    public class Form1: Form 
    {
       EditBox edit1 = new EditBox();
    
       void TextChanging(object source, EventArgs e) 
       {
          throw new RuntimeException("Invalid edit");
       }
    

参照

クラス ライブラリ開発者向けのデザイン ガイドライン | イベントの名前付けのガイドライン | クラス メンバの使用方法のガイドライン