久しぶりのReactivePropertyネタです。
ReactiveProperty, ReadOnlyReactiveProperty, ReactiveCommand等は、地味にIDisposableを実装しています。 IDisposableを実装しているということは、Disposeをしないといけないということになります。
Disposeしなくてもいいケース
ただ、必ずしもDisposeしないとまずいかというとそうでもありません。例えば以下のようなケース。
public ReactiveProperty<string> Input { get; } = new ReactiveProperty<string>();
自己完結してるような時は特にDispose必要ありません。
Disposeしないといけないケース
他のIObservableをソースとしてReactivePropertyなんかを作ったときは、内部動作としてSubscribeをしているので、Disposeを呼ぶ必要があります。例えば以下のようなケースです。
public ReactiveProperty<string> Name { get; } public Ctor(Person model) { // ObservePropertyでPropertyChangedを購読して、それをSubscribeしている!this.Name = model.ObserveProperty(x => x.Name).ToReactiveProperty(); }
こういう時は、ReactivePropertyを持っているクラスが不要になったタイミングでDisposeを呼んでやらないと、予期せぬ動作をすることがあるかもしれません。
Disposeを楽にする方法
1つ1つDisposeを呼んで回るのは大変なのでReactive ExtensionsのCompositeDisposableに、Addしていって一括Disposeができるようにするのが楽でいいです。
private CompositeDisposable Disposable { get; } = new CompositeDisposable(); // RPの定義public ReactiveProperty<string> PropA { get; } public ReactiveProperty<string> PropB { get; } public Ctor() { this.PropA = hogeObservable.ToReactiveProperty(); this.PropB = fugaObservable.ToReactiveProperty(); // Disposeを集めておくthis.Disposable.Add(this.PropA); this.Disposable.Add(this.PropA); } public SomeCleanupMethod() { // 一括Dispose!this.Disposable.Disopose(); }
ただ、ReactivePropertyを生成するのと、CompositeDisposableに集めるのと別ステートメントになってめんどくさいです。ということで、IDisposableの拡張メソッドとしてAddToメソッドを提供しています。これを使うと以下のように書けるようになります。
private CompositeDisposable Disposable { get; } = new CompositeDisposable(); // RPの定義public ReactiveProperty<string> PropA { get; } public ReactiveProperty<string> PropB { get; } public Ctor() { // RPを作りつつCompositeDisposableに登録できるthis.PropA = hogeObservable.ToReactiveProperty().AddTo(this.Disposable); this.PropB = fugaObservable.ToReactiveProperty().AddTo(this.Disposable); } public SomeCleanupMethod() { // 一括Dispose!this.Disposable.Disopose(); }
まとめ
ということで、後始末はきちんとしましょう!そして、楽に後始末するためにはCompositeDisposableとAddToメソッドを使いましょうということでした。