[C#] 25. イベント(event)キーワードを使い方


Study / C#    作成日付 : 2019/07/16 00:48:03   修正日付 : 2021/09/08 18:18:07

こんにちは。明月です。


この投稿はC#でのイベント(event)キーワードを使い方に関する説明です。


プログラム言語ではイベント(event)の意味ではユーザの行動あるいはプログラム的にはアクションが発生する時、実行される関数という意味です。

つまり、ウィンドウフォームでボタンがある場合、ユーザがボタンをクリックすると実行される関数という意味です。

using System;
using System.Windows.Forms;

namespace Example
{
  // Window formクラスを継承
  class Program : Form
  {
    // シングルスレッド設定
    [STAThread]    
    static void Main(string[] args)
    {
      // Programクラスのインスタンスを生成
      Program p = new Program();
      // Buttonクラスのインスタンスを生成
      Button btn = new Button();
      // Buttonのテキスト設定
      btn.Text = "Button";
      // ボタンをクリックするとデリゲートによりButtton_Click関数が呼び出す。
      btn.Click += Buttton_Click;
      // ウィンドウフォームのインスタンスにボタンのインスタンスを追加
      p.Controls.Add(btn);

      Application.Run(p);
    }
    // ボタンをクリックすると実行するイベント関数
    private static void Buttton_Click(object sender, EventArgs e)
    {
      // メッセージボックス出力
      MessageBox.Show("Hello");
    }
  }
}


上の例では簡単なウィンドウフォームを作成しました。

実行するとボタンがあるウィンドウフォームが生成されますが、ここでボタンをクリックするとButtton_Click関数が呼び出して実行されます。

こんなアクションをイベントと言います。


我々が以前の投稿で似ている機能に関して、デリゲート(delegate)で説明したことがあります。

link - [C#] 23. デリゲート(delegate)

using System;

namespace Example
{
  // コンソールコマンドクラス
  class ConsoleCmmand
  {
    // デリゲート生成
    public delegate void PrintDelegate(string str);
    // デリゲートリスト
    public PrintDelegate list;
    // コンストラクタ
    public ConsoleCmmand()
    {
      // 無限ループ
      while (true)
      {
        // コンソール出力
        Console.Write("Command?   ");
        // ユーザから文字列を受け取る。
        String cmd = Console.ReadLine();
        // デリゲートに登録された関数を実行
        list(cmd);
        // もし、ユーザから受け取った文字列がexitなら
        if ("EXIT".Equals(cmd, StringComparison.OrdinalIgnoreCase))
        {
          // 無限ループ終了
          break;
        }
      }
    }
  }
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // コンソールコマンドクラスのインスタンスを生成
      ConsoleCmmand c = new ConsoleCmmand();
      // イベント登録
      c.list += Print_Event;
      // 任意のキーを押してください
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
    // ユーザから入力を受け取ったらイベント発生。
    static void Print_Event(string str)
    {
      // コンソール出力
      Console.WriteLine("Echo - " + str);
      Console.WriteLine();
    }
  }
}


上のソースはコンソールからユーザで入力イベントを受け取ったらPrint_Event関数を発生します。

ここまでみるとデリゲートだけでイベント関数を実装しました。


ここまでだけでもイベント関数を実装することでは問題がありませんが、実はここにはオブジェクト指向プログラミング(OOP)のルール違反があります。

それがConsoleCmmandのデリゲートリストです。


上のデリゲートの呼び出しをコンストラクタ中でユーザから入力が発生すると実行する役割です。

でも、このリストがpublicで設定されているので、list("")形式でMain関数でも実行できることが欠点があります。


つまり、外部からはイベント関数を連結することが可能にしますが、実行はできないようにするべきです。

それがeventキーワードです。

using System;

namespace Example
{
  // コンソールコマンドクラス
  class ConsoleCmmand
  {
    // デリゲート生成
    public delegate void PrintDelegate(string str);
    // デリゲート
    public PrintDelegate list;
  }
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // インスタンスを生成
      ConsoleCmmand c = new ConsoleCmmand();
      // イベント登録
      c.list += Print_Event;

      // デリゲート実行
      c.list("Hello world");

      // 任意のキーを押してください
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
    // コンソール出力イベント
    static void Print_Event(string str)
    {
      // コンソール出力
      Console.WriteLine(str);
      Console.WriteLine();
    }
  }
}


上の例をみればMain関数でデリゲートを実行しました。実はこんなことになるとクラス中で縛っているイベントが外部から強制(?)に実行される問題があります。

それならデリゲートの前でイベント付けたらどのようになるか?

using System;

namespace Example
{
  // コンソールコマンドクラス
  class ConsoleCmmand
  {
    // デリゲート生成
    public delegate void PrintDelegate(string str);
    // デリゲート
    public event PrintDelegate list;
  }
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // インスタンスを生成
      ConsoleCmmand c = new ConsoleCmmand();
      // イベント登録
      c.list += Print_Event;

      // デリゲート実行
      c.list("Hello world");

      // 任意のキーを押してください
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
    // コンソール出力イベント
    static void Print_Event(string str)
    {
      // コンソール出力
      Console.WriteLine(str);
      Console.WriteLine();
    }
  }
}


コンパイル段階でエラーが発生しました。

つまり、イベントの関数を外部で付けることは可能ですが、実行はクラス中だけで実行することが可能です。

using System;

namespace Example
{
  // コンソールコマンドクラス
  class ConsoleCmmand
  {
    // デリゲート生成
    public delegate void PrintDelegate(string str);
    // デリゲート
    public event PrintDelegate list;
    // イベント実行関数
    public void Execute()
    {
      // イベント実行
      list("Execute");
    }
  }
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // インスタンスを生成
      ConsoleCmmand c = new ConsoleCmmand();
      // イベント登録
      c.list += Print_Event;
      // イベント実行
      c.Execute();

      // 任意のキーを押してください
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
    // コンソール出力イベント
    static void Print_Event(string str)
    {
      // コンソール出力
      Console.WriteLine(str);
      Console.WriteLine();
    }
  }
}


要約すればイベント関数は以前のデリゲートから実行を我部で実行できないためのキーワードです。


ここまでC#でのイベント(event)キーワードを使い方に関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

#C#
最新投稿