はじめに
C#6.0では、以前から望まれていた機能が多く実装され、以前よりも「かゆいところに手が届く」言語になりました。それによって、以前は意外と面倒だったイベントの実装も、C#6.0からはスマートに実装できるようになりました。
本投稿では、C#6.0時代のスマートなイベント実装方法を解説します。
従来のやり方
データを持たないイベント
public event EventHandler MyEvent;
protected virtual void OnMyEvent(EventArgs e)
{
if(e != null)
MyEvent(this, e);
}
データを持つイベント
public event EventHandler<MyEventArgs MyEvent;
protected virtual void OnMyEvent(MyEventArgs e)
{
if(e != null)
MyEvent(this, e);
}
c#6.0時代のイベント
データを持たないイベント
public event EventHandler MyEvent;
protected virtual void OnMyEvent()
{
MyEvent?.Invoke(this, EventArgs.Empty);
}
データを持つイベント
public event EventHandler<MyEventArgs MyEvent;
protected virtual void OnMyEvent(MyEventArgs e)
{
MyEvent?.Invoke(this, e);
}
解説
C#6.0でのイベントの実装は、null条件演算子の登場によって簡潔になりました。
まずは、C#6.0とは関係ない部分ではありますが、OnMyEvent
の引数について。イベントがデータを持つ必要がない場合、EventArgs
を使用することになります。この場合、EventArgsをわざわざ引数に取る必要はなく、EventArgs.Empty
を使用すれば十分です
new EventArgs()
を使用してもよいのですが、EventArgs.Empty
はstatic readonly
なフィールドであり、インスタンスを一つしか作成しないため、こちらのほうがパフォーマンスに優れています。
次に、今回のメインとなるnull条件演算子についてです。null条件演算子は単なるメンバへのアクセスに非常に似ていおり、違いは、レシーバがnullの場合にメンバへのアクセスを行わずnullを返す、ということのみです。これにより「nullでなければxxxする」という処理が完結に記述できるようになりました。
// C#6.0より前
if(obj != null)
obj.hoge()
// C#6.0
obj?.hoge()
しかし、イベントの呼び出しはMyEvent(e)
のように行うため、このままではnull条件演算子が使用できません。これに対する解決策は以下の二通りが考えられます。なお、ReSharperが後者のコードを生成するため、私は後者を使用しています。
this?.MyEvent(e)
MyEvent.Invoke(this, e);
まとめ
ここで紹介したように、C#6.0からはイベントが簡潔に実装できるようになりました。C#6.0には他にも、例外フィルタや自動実装プロパティの初期化など、ちょっと面倒だったコードが簡潔に記述できるようになりました。
まずます便利になったC#で、楽しいプログラミングライフを!