[C#] 24. 이벤트(event) 키워드 사용법


Study/C#  2021. 9. 8. 17:46

안녕하세요. 명월입니다.


이 글은 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 함수가 호출이 되고 실행이 됩니다.

이러한 액션을 이벤트라고 합니다.


우리가 예전에 비슷한 기능에 대해서는 델리게이트에서 설명을 했습니다.

링크 - [C#] 22. 델리 게이트(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) 키워드 사용법에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.