イベント
-
eventはクラスから通知を送りたいときに使う。
通知(イベント発火)されたときの処理内容はデリゲートで設定できる。 -
実装としての
event
はデリゲートにつけるアクセス修飾子。
イベント発火時の引数をシグネチャとしたデリゲートを定義し、そこにevent
キーワードをつける。
event
をつけない場合、外部からデリゲートを実行できてしまうなど問題がおきる。
また、またevent
にすると、+=
でしかデリゲートを代入できなくなるなど、event
を使うことで安全に実装することができるようになる。 -
なお引数のシグネチャは自分自身の
sender
と、引数をまとめたクラスe
とするのが習わし。
public class EvenSample1
{
public delegate void OrgEventHandler(object sender, EventArgs e);
public event OrgEventHandler? TestEvent;
public void Test()
{
if (TestEvent != null) TestEvent(this, EventArgs.Empty);
}
}
public class EventSampleTest(ITestOutputHelper output)
{
[Fact]
public void a()
{
var a = new EvenSample1();
a.TestEvent += (sender, e) =>
{
Assert.Equal(a, sender);
};
a.Test();
}
}
組み込みに EventHandler<TEventArgs> デリゲートがあるので、自身でデリゲートを定義する必要は基本的にない。
public class EvenSample2
{
public event EventHandler<EventArgs>? TestEvent;
public void Test()
{
if (TestEvent != null) TestEvent(this, EventArgs.Empty);
}
}
public class EventSampleTest(ITestOutputHelper output)
{
[Fact]
public void b()
{
var a = new EvenSample2();
a.TestEvent += (sender, e) =>
{
Assert.Equal(a, sender);
};
a.Test();
}
}
EventArgs
はプロパティを持たない空のクラスなので、
引数を追加したい場合は以下のようにEventArgs
を継承したクラスを作る。
public class TestEventArgs : EventArgs
{
public string Hoge { get; set; }
}
public class EvenSample3
{
public event EventHandler<TestEventArgs>? TestEvent;
public void Test()
{
var ea = new TestEventArgs();
ea.Hoge = "TEST";
if (TestEvent != null) TestEvent(this, ea);
}
}
public class EventSampleTest(ITestOutputHelper output)
{
[Fact]
public void c()
{
var a = new EvenSample3();
a.TestEvent += (sender, e) =>
{
Assert.Equal(a, sender);
Assert.Equal("TEST", e.Hoge);
};
a.Test();
}
}