3

同じインターフェイスを実装する 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仕様の見落とし?意図的な設計上の決定?

4

2 に答える 2

1

警告として、これは解決されたように見えますが、IObservable / IObserverはすべてのプラットフォームで共分散ではありません。具体的には、WP7とSilverlightは、インターフェイス宣言から共分散を取り除くことにしました。

于 2013-01-31T00:55:18.827 に答える
1

ここでの問題は、私のイベントタイプがstructsであったため、オブジェクトに自動的にボックス化されなかったことです。タイプを変更classしてトリックを行いました。

于 2013-01-31T19:41:37.537 に答える