使用无限数设置压缩Rx IObservable

时间:2010-03-24 22:00:57

标签: linq operating-system c#-4.0 system.reactive

我有一个来自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还没有收到任何事件。

3 个答案:

答案 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() {
    }