我有一个来自Reactive扩展框架的IObservable [下面示例中的命名行],我想为它观察到的每个对象添加索引号。
我尝试使用Zip函数实现这个:
rows.Zip(Enumerable.Range(1, int.MaxValue), (row, index) =>
new { Row = row, Index = index })
.Subscribe(a => ProcessRow(a.Row, a.Index), () => Completed());
..但遗憾的是这会抛出
ArgumentOutOfRangeException: 指定的参数超出了有效值的范围。 参数名称:一次性用品
我是否理解Zip函数错误或我的代码有问题?
代码的Range部分似乎不是问题,IObservable还没有收到任何事件。
答案 0 :(得分:1)
.Select有一个重载来包含索引:
rows.Select((row, index) => new { row, index });
答案 1 :(得分:0)
显然,Zip扩展方法将原始的自定义IObservable转换为匿名的observable,并且订阅它会创建一个System.Collections.Generic.AnonymousObserver,它不实现IDisposable。 因此,您无法以正常方式实现Subscribe方法(至少我已经看过它使用的方式),这是
public IDisposable Subscribe(IObserver<T> observer) {
// ..add to observer list..
return observer as IDisposable
}
更可能的正确答案是:
return Disposable.Create(() => Observers.Remove(observer));
你应该注意到碰撞可能会在完成方法中被修改,所以在处理之前创建一个列表的副本:
public void Completed()
{
foreach (var observer in Observers.ToList())
{
observer.OnCompleted();
}
}
答案 2 :(得分:0)
我不确定你的问题是什么,这对你有用吗(你在这里缺少什么?):
static void Main(string[] args)
{
var rows = new List<int> { 4,5,1,2,5 }.ToObservable();
rows.Zip(Enumerable.Range(1, int.MaxValue), (row, index) =>
new { Row = row, Index = index })
.Subscribe(a => ProcessRow(a.Row, a.Index), () => Completed());
Console.ReadLine();
}
static void ProcessRow(int row, int index) {
Console.WriteLine("Row {0}, Index {1}", row, index);
}
static void Completed() {
}