C#でアプリケーション開発を行う際に頻繁に登場する「イベント」。ボタンをクリックしたときや、タイマーが一定時間を経過したときなど、ユーザーやシステムからのアクションに応じて特定の処理を行いたい場面は多々あります。
しかし、「イベント」と「デリゲート」の違いや、どうやって自作クラスにイベントを組み込めばいいのか、初心者には少し難しく感じるかもしれません。
この記事では、C#におけるイベントの基本的な仕組みから使い方、自作イベントの作成方法まで、実例を交えながらわかりやすく解説します。
C#の「イベント」とは、あるオブジェクト内で特定のアクションが発生したことを他のオブジェクトに通知する仕組みです。たとえば、ボタンがクリックされたとき、テキストボックスの文字が変更されたときなどに処理を行う必要がある場面で活用されます。
イベントは「通知する側(イベント発行元)」と「受け取って処理する側(イベント購読者)」に分かれていて、疎結合な構造を実現できるのが特徴です。
C#のイベントは、内部的にはデリゲート(delegate)という仕組みを利用しています。
デリゲートは「関数の参照を保持できる型」であり、イベントはそのデリゲートをラップして「他のクラスに通知する手段」として提供されているものです。
public delegate void Notify(); // デリゲート型の定義
public class Notifier
{
public Notify OnNotify; // デリゲートのインスタンス
}
public class Notifier
{
public event Notify OnNotify; // デリゲートをイベントとして宣言
}
「event」キーワードが付くことで、外部からの操作が制限され、安全に通知専用の機能として使うことができます。
ここでは、イベントの仕組みを使って、「ある条件を満たすと通知する」簡単な例を紹介します。
public class TemperatureMonitor
{
public delegate void TemperatureExceededHandler(double temp);
public event TemperatureExceededHandler OnTemperatureExceeded;
public void CheckTemperature(double currentTemp)
{
if (currentTemp > 30.0)
{
OnTemperatureExceeded?.Invoke(currentTemp);
}
}
}
public class AlertSystem
{
public void ShowWarning(double temp)
{
Console.WriteLine($"警告:温度が高すぎます!現在の温度:{temp}度");
}
}
class Program
{
static void Main()
{
TemperatureMonitor monitor = new TemperatureMonitor();
AlertSystem alert = new AlertSystem();
monitor.OnTemperatureExceeded += alert.ShowWarning;
monitor.CheckTemperature(32.5); // ⇒ 警告メッセージが表示される
}
}
このように、イベントにメソッドを登録し、条件を満たしたときだけ実行される仕組みが作れます。
.NETの標準的なイベント設計では、EventHandler
または EventHandler<TEventArgs>
を使うのが一般的です。
public class DataSender
{
public event EventHandler<DataEventArgs> DataSent;
public void SendData(string data)
{
Console.WriteLine($"データ送信中: {data}");
DataSent?.Invoke(this, new DataEventArgs(data));
}
}
public class DataEventArgs : EventArgs
{
public string Data { get; }
public DataEventArgs(string data)
{
Data = data;
}
}
public class Logger
{
public void LogData(object sender, DataEventArgs e)
{
Console.WriteLine($"ログ:{e.Data}");
}
}
class Program
{
static void Main()
{
DataSender sender = new DataSender();
Logger logger = new Logger();
sender.DataSent += logger.LogData;
sender.SendData("Hello World!");
}
}
このように、イベントの引数に必要な情報を含めることで、より汎用的で拡張性のある通知ができます。
イベントには複数のメソッドを登録できます。これを「マルチキャストデリゲート」と呼びます。
monitor.OnTemperatureExceeded += alert.ShowWarning;
monitor.OnTemperatureExceeded += (temp) => Console.WriteLine($"ログ記録:{temp}度");
このように追加することで、イベントが発生した際に複数の処理が順番に呼び出されます。
登録したイベントは以下のように削除できます。
monitor.OnTemperatureExceeded -= alert.ShowWarning;
また、イベントが null
のまま Invoke()
を呼び出すと NullReferenceException
が発生するので、?.Invoke()
を使うのが一般的です。
イベントは、ユーザーが作成するUIコンポーネントやツールライブラリにも柔軟に組み込むことができます。
「誰が何をするか」を分離できるため、保守性の高いコードを書くうえで非常に役立ちます。
C#のイベントは、ユーザー操作やシステムの状態変化に応じて処理を呼び出すための強力な仕組みです。
デリゲートをベースにした仕組みでありながら、event
キーワードによってセーフな通知方法として活用できる点が魅力です。
ポイントをまとめると:
EventHandler
を使うと標準的な書き方ができるイベントを理解することで、よりモダンで保守性の高いC#アプリケーションを開発できるようになります。まずは簡単なイベント処理から試してみましょう!