同じインターフェイスを実装する 2 つの異なるイベント タイプがあります。
interface InputEvent { }
struct KeyboardEvent : InputEvent { }
struct MouseEvent : InputEvent { }
各イベント タイプに 1 つずつ、2 つのストリームがあります。
IObservable<KeyboardEvent> KeyboardStream;
IObservable<MouseEvent> MouseStream;
IObservable<InputEvent>
両者の融合した流れを紹介したい。最初は、コンパイラが基本クラスを自動的に検出することを期待していました。
IObservable<InputEvent> Merged = Observable.Merge(KeyboardStream, MouseStream);
運が悪いので、私は明示的にしようとしました:
IObservable<InputEvent> Merged = Observable.Merge<InputEvent>(KeyboardStream, MouseStream);
いいえ、コンパイラはまだヒントを取得していません。したがって、それぞれを明示的にキャストします。
IObservable<InputEvent> Merged = Observable.Merge<InputEvent>((IObservable<InputEvent>)KeyboardStream, (IObservable<InputEvent>)MouseStream);
うん。そして、キャストの失敗で実行時にまだ失敗します。これは共分散と関係があると思います(最初の試行ではまだ完全にはわかりません...)ので、IEnumerableを使用して行うことを行います.Cast<T>()
:
IObservable<InputEvent> Merged = Observable.Merge<InputEvent>(KeyboardStream.Cast<InputEvent>(), MouseStream.Cast<InputEvent>());
今、コンパイラは、それ.Cast<T>()
が定義されているのはIObservable<Object>
...何ですか?それはかなり不便で不必要な拘束のようです。
最後に、単純な選択を試みます。
IObservable<InputEvent> Merged = Observable.Merge(KeyboardStream.Select(i => (InputEvent)i), MouseStream.Select(i => (InputEvent)i));
ついに成功!それは機能し、そこから独自の単純な拡張メソッドを作成できます。ただし、ビルトイン.Cast<T>()
と.OfType<T>()
オペレーターはかなり嫌な味がします。だから私の質問は次のとおりです。かなり冗長なオブザーバブル以外で組み込みの拡張機能を使用できないのはなぜですか? .Cast<T>()
Object
それは共分散の問題ですか?Rx仕様の見落とし?意図的な設計上の決定?