イベントの処理と発生Handling and raising events

.NET でのイベントは、デリゲート モデルに基づいています。Events in .NET are based on the delegate model. デリゲート モデルはオブザーバー デザイン パターンに従って、サブスクライバーがプロバイダーに登録して通知を受信できるようにします。The delegate model follows the observer design pattern, which enables a subscriber to register with and receive notifications from a provider. イベントの送信元がイベント発生の通知をプッシュしたら、イベント レシーバーはその通知を受信して、通知に対する応答を定義します。An event sender pushes a notification that an event has happened, and an event receiver receives that notification and defines a response to it. ここでは、デリゲート モデルの主要コンポーネント、アプリケーションでイベントを利用する方法、およびコードでイベントを実装する方法について説明します。This article describes the major components of the delegate model, how to consume events in applications, and how to implement events in your code.

Windows 8.x ストア アプリでのイベントの処理については、「Events and routed events overview」(イベントとルーティング イベントの概要) を参照してください。For information about handling events in Windows 8.x Store apps, see Events and routed events overview.

イベントEvents

イベントは、アクションの発生を知らせるために、オブジェクトによって送信されるメッセージです。An event is a message sent by an object to signal the occurrence of an action. アクションは、ユーザーがボタンのクリックなどの対話的操作を行った場合や、プロパティの値の変更など、なんらかのプログラム ロジックによって発生します。The action can be caused by user interaction, such as a button click, or it can result from some other program logic, such as changing a property’s value. イベントを発生させるオブジェクトを "イベントの送信元" と呼びます。The object that raises the event is called the event sender. イベントの送信元は、発生させたイベントをどのオブジェクトまたはメソッドが受信する (処理する) かについての情報を持っていません。The event sender doesn't know which object or method will receive (handle) the events it raises. このイベントはイベントの送信元のメンバーです。たとえば、Click イベントは Button クラスのメンバーであり、PropertyChanged イベントは INotifyPropertyChanged インターフェイスを実装するクラスのメンバーです。The event is typically a member of the event sender; for example, the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that implements the INotifyPropertyChanged interface.

イベントを定義するには、イベント クラスのシグネチャで C# の event または Visual Basic の Event キーワードを使用し、イベント用のデリゲートの型を指定します。To define an event, you use the C# event or the Visual Basic Event keyword in the signature of your event class, and specify the type of delegate for the event. デリゲートについては、次のセクションで説明します。Delegates are described in the next section.

通常、イベントを発生させるには、protectedvirtual (C# の場合)、または ProtectedOverridable (Visual Basic の場合) としてマークされたメソッドを追加します。Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and Overridable (in Visual Basic). このメソッドには OnEventName の形式で名前を付けます (OnDataReceived など)。Name this method OnEventName; for example, OnDataReceived. メソッドでは、イベント データ オブジェクトを指定するパラメーターを 1 つ受け取る必要があります。これは、EventArgs 型または派生型のオブジェクトです。The method should take one parameter that specifies an event data object, which is an object of type EventArgs or a derived type. このメソッドを指定すると、イベントを発生させるためのロジックを派生クラスでオーバーライドできます。You provide this method to enable derived classes to override the logic for raising the event. 派生クラスは常に基底クラスの OnEventName メソッドを呼び出して、登録されたデリゲートがイベントを必ず受信できるようにします。A derived class should always call the OnEventName method of the base class to ensure that registered delegates receive the event.

次の例は、ThresholdReached という名前のイベントを宣言する方法を示しています。The following example shows how to declare an event named ThresholdReached. イベントは EventHandler デリゲートに関連付けられ、OnThresholdReached という名前のメソッドで発生します。The event is associated with the EventHandler delegate and raised in a method named OnThresholdReached.

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.Invoke(this, e);
    }

    // provide remaining implementation for the class
}
Public Class Counter
    Public Event ThresholdReached As EventHandler

    Protected Overridable Sub OnThresholdReached(e As EventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub

    ' provide remaining implementation for the class
End Class

デリゲートDelegates

デリゲートは、メソッドへの参照を保持する型です。A delegate is a type that holds a reference to a method. デリゲートは、それが参照するメソッドの戻り値とパラメーターを示すシグネチャを使って宣言され、そのシグネチャに一致するメソッドへの参照だけを保持できます。A delegate is declared with a signature that shows the return type and parameters for the methods it references, and it can hold references only to methods that match its signature. これにより、デリゲートはタイプ セーフな関数ポインターやコールバックと同等の機能を持つことができます。A delegate is thus equivalent to a type-safe function pointer or a callback. デリゲート クラスは、宣言すると、定義は不要です。A delegate declaration is sufficient to define a delegate class.

.NET でのデリゲートの用途は多数あります。Delegates have many uses in .NET. イベントのコンテキストでは、デリゲートは、イベント ソースとイベントを処理するコードの間を仲介するもの、つまりポインター的な機構です。In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. デリゲートをイベントに関連付けるには、デリゲート型をイベント宣言に追加します。You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. デリゲートの詳細については、「Delegate クラス」を参照してください。For more information about delegates, see the Delegate class.

.NET には EventHandler および EventHandler<TEventArgs> デリゲートが用意されていて、ほとんどのイベント シナリオがサポートされます。.NET provides the EventHandler and EventHandler<TEventArgs> delegates to support most event scenarios. EventHandler デリゲートは、イベント データを含まないすべてのイベントに対して使用します。Use the EventHandler delegate for all events that do not include event data. EventHandler<TEventArgs> デリゲートは、イベントに関するデータを含むイベントに使用します。Use the EventHandler<TEventArgs> delegate for events that include data about the event. これらのデリゲートには戻り値の型の値がなく、2 つのパラメーター (イベント ソース用オブジェクトとイベント データ用オブジェクト) を受け取ります。These delegates have no return type value and take two parameters (an object for the source of the event, and an object for event data).

デリゲートはマルチキャストです。つまり、複数のイベント処理メソッドへの参照を保持できます。Delegates are multicast, which means that they can hold references to more than one event-handling method. 詳細については、Delegate のリファレンス ページを参照してください。For details, see the Delegate reference page. デリゲートでは、イベント処理を柔軟に、そして詳細に制御できます。Delegates provide flexibility and fine-grained control in event handling. デリゲートは、イベントに対して登録されているイベント ハンドラーのリストを管理することで、そのイベントを発生させるクラスのイベント ディスパッチャーとして動作します。A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event.

EventHandler デリゲートおよび EventHandler<TEventArgs> デリゲートが動作しないシナリオについては、デリゲートを定義できます。For scenarios where the EventHandler and EventHandler<TEventArgs> delegates do not work, you can define a delegate. デリゲートの定義が必要なシナリオは非常にまれで、たとえば、ジェネリックを認識しないコードを使用する必要がある場合などです。Scenarios that require you to define a delegate are very rare, such as when you must work with code that does not recognize generics. デリゲートは、宣言内で C# の delegate および Visual Basic の Delegate キーワードを使ってマークします。You mark a delegate with the C# delegate and Visual Basic Delegate keyword in the declaration. 次の例は、ThresholdReachedEventHandler という名前のデリゲートを宣言する方法を示しています。The following example shows how to declare a delegate named ThresholdReachedEventHandler.

public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)

イベント データEvent data

イベントに関連付けられたデータは、イベント データ クラスを使用して提供できます。Data that is associated with an event can be provided through an event data class. .NET には、ご自分のアプリケーション内で使用できるイベント データ クラスが多数用意されています。.NET provides many event data classes that you can use in your applications. たとえば、SerialDataReceivedEventArgs クラスは、SerialPort.DataReceived イベントのイベント データ クラスです。For example, the SerialDataReceivedEventArgs class is the event data class for the SerialPort.DataReceived event. .NET の名前付けパターンでは、すべてのイベント データ クラス名の末尾に EventArgs が付きます。.NET follows a naming pattern of ending all event data classes with EventArgs. イベントに関連付けられているイベント データ クラスは、そのイベントのデリゲートを見ればわかります。You determine which event data class is associated with an event by looking at the delegate for the event. たとえば、SerialDataReceivedEventHandler デリゲートには、パラメーターの 1 つとして SerialDataReceivedEventArgs クラスが含まれます。For example, the SerialDataReceivedEventHandler delegate includes the SerialDataReceivedEventArgs class as one of its parameters.

EventArgs は、すべてのイベント データ クラスの基本型です。The EventArgs class is the base type for all event data classes. また、EventArgs は、イベントにデータが関連付けられていないときに使用するクラスでもあります。EventArgs is also the class you use when an event does not have any data associated with it. 何かが発生したことを他のクラスに通知することのみが目的のイベント、つまり、データの受け渡しを必要としないイベントを作成する場合は、デリゲートの 2 番目のパラメーターとして EventArgs クラスを追加します。When you create an event that is only meant to notify other classes that something happened and does not need to pass any data, include the EventArgs class as the second parameter in the delegate. データが指定されていない場合は、EventArgs.Empty 値を渡すことができます。You can pass the EventArgs.Empty value when no data is provided. EventHandler デリゲートには、パラメーターとして EventArgs クラスが含まれます。The EventHandler delegate includes the EventArgs class as a parameter.

カスタマイズされたイベント データ クラスを作成する場合は、EventArgsから派生したクラスを作成し、イベントに関連するデータを渡すのに必要なメンバーを指定します。When you want to create a customized event data class, create a class that derives from EventArgs, and then provide any members needed to pass data that is related to the event. 通常は、.NET と同じ名前付けパターンを使い、イベント データ クラス名の末尾に EventArgs を付ける必要があります。Typically, you should use the same naming pattern as .NET and end your event data class name with EventArgs.

次の例は、ThresholdReachedEventArgs という名前のイベント データを示しています。The following example shows an event data class named ThresholdReachedEventArgs. これには、発生したイベントに応じた特定のプロパティが含まれます。It contains properties that are specific to the event being raised.

public class ThresholdReachedEventArgs : EventArgs
{
    public int Threshold { get; set; }
    public DateTime TimeReached { get; set; }
}
Public Class ThresholdReachedEventArgs
    Inherits EventArgs

    Public Property Threshold As Integer
    Public Property TimeReached As DateTime
End Class

イベント ハンドラーEvent handlers

イベントに応答するには、イベント レシーバーのイベント ハンドラー メソッドを定義します。To respond to an event, you define an event handler method in the event receiver. このメソッドは、処理するイベントのデリゲートのシグネチャと一致する必要があります。This method must match the signature of the delegate for the event you are handling. イベント ハンドラーでは、ユーザーがボタンをクリックしたときにユーザー入力を収集するなど、イベントが発生したときに必要なアクションを実行します。In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user clicks a button. イベントが発生したときに通知を受け取るには、イベント ハンドラー メソッドがイベントをサブスクライブする必要があります。To receive notifications when the event occurs, your event handler method must subscribe to the event.

次の例は、c_ThresholdReached デリゲートのシグネチャと一致する、EventHandler という名前のイベント ハンドラー メソッドを示しています。The following example shows an event handler method named c_ThresholdReached that matches the signature for the EventHandler delegate. メソッドは、ThresholdReached イベントをサブスクライブします。The method subscribes to the ThresholdReached event.

class Program
{
    static void Main()
    {
        var c = new Counter();
        c.ThresholdReached += c_ThresholdReached;

        // provide remaining implementation for the class
    }

    static void c_ThresholdReached(object sender, EventArgs e)
    {
        Console.WriteLine("The threshold was reached.");
    }
}
Module Module1

    Sub Main()
        Dim c As New Counter()
        AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

        ' provide remaining implementation for the class
    End Sub

    Sub c_ThresholdReached(sender As Object, e As EventArgs)
        Console.WriteLine("The threshold was reached.")
    End Sub
End Module

静的および動的イベント ハンドラーStatic and dynamic event handlers

.NET を使用すると、静的または動的にイベント通知のためのサブスクライバーを登録できます。.NET allows subscribers to register for event notifications either statically or dynamically. 静的なイベント ハンドラーは、処理対象のイベントのクラスの有効期間にわたって有効になります。Static event handlers are in effect for the entire life of the class whose events they handle. 動的なイベント ハンドラーは、プログラムの実行中、通常は条件付きのプログラム ロジックに応答する形で、明示的にアクティブ化または非アクティブ化されます。Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. たとえば、特定の条件下でのみイベント通知が必要な場合や、複数のイベント ハンドラーを持つアプリケーションで、実行時の条件に応じて適切なハンドラーを決定する場合などに使用できます。For example, they can be used if event notifications are needed only under certain conditions or if an application provides multiple event handlers and run-time conditions define the appropriate one to use. 前のセクションの例は、イベント ハンドラーを動的に追加する方法を示しています。The example in the previous section shows how to dynamically add an event handler. 詳細については、イベント (Visual Basic の場合) とイベント (C# の場合) を参照してください。For more information, see Events (in Visual Basic) and Events (in C#).

複数のイベントの発生Raising multiple events

クラスで複数のイベントを発生させる場合、コンパイラでは、イベント デリゲートのインスタンスごとに 1 つのフィールドが生成されます。If your class raises multiple events, the compiler generates one field per event delegate instance. イベントの数が多い場合は、デリゲート 1 つあたり 1 フィールドというストレージ コストが許容されない可能性があります。If the number of events is large, the storage cost of one field per delegate may not be acceptable. そのような状況に備えて、.NET には、イベント デリゲートを格納するために任意に選択した別のデータ構造と一緒に使用できる、イベント プロパティが用意されています。For those situations, .NET provides event properties that you can use with another data structure of your choice to store event delegates.

イベント プロパティは、イベント アクセサーを伴うイベント宣言によって構成されます。Event properties consist of event declarations accompanied by event accessors. イベント アクセサーは、ストレージ データ構造におけるイベント デリゲート インスタンスの追加または削除を定義するメソッドです。Event accessors are methods that you define to add or remove event delegate instances from the storage data structure. イベント プロパティを使用すると、イベント プロパティは各イベント デリゲートを呼び出す前に取得する必要があるので、イベント フィールドよりも低速です。Note that event properties are slower than event fields, because each event delegate must be retrieved before it can be invoked. つまり、メモリを取るか、速度を取るかの比較検討になります。The trade-off is between memory and speed. クラスで、発生頻度の低いイベントを数多く定義する場合は、イベント プロパティを実装することをお勧めします。If your class defines many events that are infrequently raised, you will want to implement event properties. 詳細については、「方法 :イベント プロパティを使用して複数のイベントを処理する」をご覧ください。For more information, see How to: Handle Multiple Events Using Event Properties.

TitleTitle 説明Description
方法: イベントを発生させる/処理するHow to: Raise and Consume Events イベントの発生例と実装例が含まれます。Contains examples of raising and consuming events.
方法: イベント プロパティを使用して複数のイベントを処理するHow to: Handle Multiple Events Using Event Properties イベント プロパティを使用して複数のイベントを処理する方法を示します。Shows how to use event properties to handle multiple events.
オブサーバー デザイン パターンObserver Design Pattern サブスクライバーがプロバイダーに登録して、通知を受信できるようにするデザイン パターンについて説明します。Describes the design pattern that enables a subscriber to register with, and receive notifications from, a provider.
方法: Web フォーム アプリケーションでイベントを利用するHow to: Consume Events in a Web Forms Application Web フォーム コントロールによって発生したイベントを処理する方法を示します。Shows how to handle an event that is raised by a Web Forms control.

関連項目See also