我有两种不同的事件类型实现相同的接口:
interface InputEvent { }
struct KeyboardEvent : InputEvent { }
struct MouseEvent : InputEvent { }
我有两个流,每种事件类型之一:
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>()
运算符在我的嘴里留下了非常糟糕的味道。所以我的问题是:为什么我不能在任何 observable 上使用内置.Cast<T>()
扩展,除了Object
它几乎是多余的?这是协方差问题吗?Rx 规范中的疏忽?一个深思熟虑的设计决定?