リファレンス
Observable、ObservableList、ObservableDictionary のすべてのメンバーと、それぞれが何を通知するか。
すべて Udonite.Observables にあります。
Observable<T>
new Observable<int>() // 既定値。誰にも通知しない
new Observable<int>(7) // 初期値つき。誰にも通知しない
| メンバー | 通知 |
|---|---|
T Value { get; set; } |
設定時。値が違うときだけ |
Subscribe(Action<T> handler) |
しない |
Subscribe(Action<T> handler, bool notifyNow) |
notifyNow はこのハンドラだけを呼ぶ |
Unsubscribe(Action<T> handler) |
しない。購読していないものを外しても何も起きない |
UnsubscribeAll() |
しない |
SetSilently(T value) |
しない |
Publish() |
する。変わっていなくても全購読者 |
bool CascadeStalled { get; } |
しない |
ToString() |
しない。値、値がなければ "" |
等価判定は object.Equals です。 等しい文字列どうしは変更ではありません。null も他と同じひとつの値なので、null から null は静かで、null から値への変化はそうではありません。
二度購読しても一度分です。 そうなる典型は Start がもう一度走ったときで、変更のたびに二回呼ばれるのは常にバグです。
購読者はどこにいても構いません。 score.Subscribe(display.Show) は別のビヘイビア上のハンドラに届き、score.Subscribe(OnChanged) はこのビヘイビア上のものに届きます。ビヘイビアでないクラスは、自分の中から自分のメソッドを購読します。ひとつの Observable がこの三種類を混ぜて持てます。
例外は、ビヘイビアでないクラスの他のオブジェクトのメソッドを渡すときです。tally がただのクラスである score.Subscribe(tally.Add) は、Udon にレシーバを置く場所がないため拒否されます。そのクラスに自分で購読させるメソッドを持たせてください。
public class Tally
{
public void Watch(Observable<int> score) { score.Subscribe(Add); }
private void Add(int value) { ... }
}
購読者数はなく、Unsubscribe は何も返しません。 削除は内容で一致するので、追加したときの値そのものでなくその場で作り直したデリゲートでも外せます。ただし Udon には購読者の一覧を覗く手段が登録されていません。何を購読したか知る必要があるコードは、自分で覚えておいてください。
CascadeStalled は、十六回やり直しても収まらなかった publish を報告します。そこに至るには同じオブザーバブルへ書き戻す購読者が要り、コンパイラはそれを断るので、ワールドでは false のままです。
ObservableList<T>
購読者は Action<ObservableList<T>> を取り、リスト自身を受け取ります。
| メンバー | 通知 | LastChange |
|---|---|---|
T this[int] { get; set; } |
設定時。違うときだけ | Replaced |
Add(T) |
する | Added |
AddRange(T[]) |
範囲全体で一度。空や null なら何もしない | None |
Insert(int, T) |
する | Added |
bool Remove(T) |
あった場合だけ | Removed |
RemoveAt(int) |
する | Removed |
Clear() |
中身があった場合だけ | Cleared |
AddSilently(T) |
しない | |
Contains、IndexOf、ToArray、Count |
しない |
ハンドラの中では LastChange、LastIndex、LastItem が何が起きたかを表すので、購読者は全部を作り直すのではなくオブジェクトをひとつ生やすだけで済みます。
private void OnNamesChanged(ObservableList<string> list)
{
if (list.LastChange == CollectionChange.Added)
Spawn(list.LastItem);
else
RedrawEverything(list);
}
これらは進行中の通知を説明するもので、意味を持つのはハンドラの中だけです。
ObservableDictionary<TKey, TValue>
購読者は Action<ObservableDictionary<TKey, TValue>> を取ります。
| メンバー | 通知 | LastChange |
|---|---|---|
TValue this[TKey] { get; } |
しない | |
Set(TKey, TValue) |
値が違うときだけ | 新しいキーなら Added、既知のキーなら Replaced |
bool Remove(TKey) |
あった場合だけ | Removed |
Clear() |
中身があった場合だけ | Cleared |
SetSilently(TKey, TValue) |
しない | |
ContainsKey、TryGetValue、Count |
しない |
LastKey と LastValue が何が変わったかを示します。
インデクサのセッターは意図的にありません。 Udon の辞書は DataDictionary で、無いキーを読むと既定値ではなくフォルトになります。セッターの内側に隠れた読み取りは罠になるので、Set は読み取りを明示のままにします。先に ContainsKey を訊くか、TryGetValue を使ってください。
CollectionChange
None、Added、Removed、Replaced、Cleared。
None は「まだ何も起きていない」と「単一の要素を伴わない一括変更」の両方です。AddRange や、変更の報告ではなくコレクションを見せている Subscribe(handler, true) がこれにあたります。
ハンドラが例外を投げたら
Udon では例外が起きるとそのセッションの間ビヘイビアが停止し、購読者ひとつ分を捕まえて次へ進むことはできません。投げたハンドラは残りの通知と、そのビヘイビアがそのあとにするはずだったことをまとめて道連れにします。ハンドラは値を読んで何かを更新するだけに留めてください。