方法: インターフェイス イベントを実装する (C# プログラミング ガイド)How to: Implement Interface Events (C# Programming Guide)

インターフェイスではイベントを宣言できます。An interface can declare an event. 次の例では、クラス内にインターフェイス イベントを実装する方法について説明します。The following example shows how to implement interface events in a class. 基本的な原則は、インターフェイスのメソッドやプロパティを実装する場合と同じです。Basically the rules are the same as when you implement any interface method or property.

クラス内でインターフェイス イベントを実装するにはTo implement interface events in a class

クラス内でイベントを宣言してから、適切な領域でそのイベントを呼び出します。Declare the event in your class and then invoke it in the appropriate areas.

namespace ImplementInterfaceEvents  
{  
    public interface IDrawingObject  
    {  
        event EventHandler ShapeChanged;  
    }  
    public class MyEventArgs : EventArgs   
    {  
        // class members  
    }  
    public class Shape : IDrawingObject  
    {  
        public event EventHandler ShapeChanged;  
        void ChangeShape()  
        {  
            // Do something here before the event…  

            OnShapeChanged(new MyEventArgs(/*arguments*/));  

            // or do something here after the event.   
        }  
        protected virtual void OnShapeChanged(MyEventArgs e)  
        {  
            ShapeChanged?.Invoke(this, e);  
        }  
    }  

}  

Example

次の例では、同じ名前のイベント名がある 2 つ以上のインターフェイスからクラスを継承するという、あまり一般的でない状況の対処方法を示します。The following example shows how to handle the less-common situation in which your class inherits from two or more interfaces and each interface has an event with the same name. このような場合は、1 つ以上のイベントに対して明示的なインターフェイスの実装を指定する必要があります。In this situation, you must provide an explicit interface implementation for at least one of the events. イベントに対する明示的なインターフェイスの実装を記述する場合、add および remove の各イベント アクセサーも記述する必要があります。When you write an explicit interface implementation for an event, you must also write the add and remove event accessors. 通常ではこれらのアクセサーはコンパイラで指定しますが、この例ではコンパイラで指定することはできません。Normally these are provided by the compiler, but in this case the compiler cannot provide them.

独自のアクセサーを指定することで、2 つのイベントがクラス内の同一イベントと別々のイベントのどちらによって表されるかを指定できます。By providing your own accessors, you can specify whether the two events are represented by the same event in your class, or by different events. たとえば、インターフェイスの仕様上、イベントを複数回発生させる必要がある場合は、各イベントをクラス内の別々の実装に関連付けます。For example, if the events should be raised at different times according to the interface specifications, you can associate each event with a separate implementation in your class. 次の例では、サブスクライバーで IShape または IDrawingObject のいずれかに図形参照をキャストして、どちらの OnDraw イベントを受信するかを決定しています。In the following example, subscribers determine which OnDraw event they will receive by casting the shape reference to either an IShape or an IDrawingObject.

namespace WrapTwoInterfaceEvents
{
    using System;

    public interface IDrawingObject
    {
        // Raise this event before drawing
        // the object.
        event EventHandler OnDraw;
    }
    public interface IShape
    {
        // Raise this event after drawing
        // the shape.
        event EventHandler OnDraw;
    }


    // Base class event publisher inherits two
    // interfaces, each with an OnDraw event
    public class Shape : IDrawingObject, IShape
    {
        // Create an event for each interface event
        event EventHandler PreDrawEvent;
        event EventHandler PostDrawEvent;

        object objectLock = new Object();

        // Explicit interface implementation required.
        // Associate IDrawingObject's event with
        // PreDrawEvent
        #region IDrawingObjectOnDraw
        event EventHandler IDrawingObject.OnDraw
        {
            add
            {
                lock (objectLock)
                {
                    PreDrawEvent += value;
                }
            }
            remove
            {
                lock (objectLock)
                {
                    PreDrawEvent -= value;
                }
            }
        }
        #endregion
        // Explicit interface implementation required.
        // Associate IShape's event with
        // PostDrawEvent
        event EventHandler IShape.OnDraw
        {
            add
            {
                lock (objectLock)
                {
                    PostDrawEvent += value;
                }
            }
            remove
            {
                lock (objectLock)
                {
                    PostDrawEvent -= value;
                }
            }


        }

        // For the sake of simplicity this one method
        // implements both interfaces. 
        public void Draw()
        {
            // Raise IDrawingObject's event before the object is drawn.
            PreDrawEvent?.Invoke(this, EventArgs.Empty);

            Console.WriteLine("Drawing a shape.");

            // Raise IShape's event after the object is drawn.
            PostDrawEvent?.Invoke(this, EventArgs.Empty);
        }
    }
    public class Subscriber1
    {
        // References the shape object as an IDrawingObject
        public Subscriber1(Shape shape)
        {
            IDrawingObject d = (IDrawingObject)shape;
            d.OnDraw += d_OnDraw;
        }

        void d_OnDraw(object sender, EventArgs e)
        {
            Console.WriteLine("Sub1 receives the IDrawingObject event.");
        }
    }
    // References the shape object as an IShape
    public class Subscriber2
    {
        public Subscriber2(Shape shape)
        {
            IShape d = (IShape)shape;
            d.OnDraw += d_OnDraw;
        }

        void d_OnDraw(object sender, EventArgs e)
        {
            Console.WriteLine("Sub2 receives the IShape event.");
        }
    }


    public class Program
    {
        static void Main(string[] args)
        {
            Shape shape = new Shape();
            Subscriber1 sub = new Subscriber1(shape);
            Subscriber2 sub2 = new Subscriber2(shape);
            shape.Draw();

            // Keep the console window open in debug mode.
            System.Console.WriteLine("Press any key to exit.");
            System.Console.ReadKey();
        }
    }

}
/* Output:
    Sub1 receives the IDrawingObject event.
    Drawing a shape.
    Sub2 receives the IShape event.
*/

関連項目See also