C#反应式扩展-内存管理和Distinct运算符

C#反应式扩展-内存管理和Distinct运算符,c#,system.reactive,C#,System.reactive,示例代码: public static IObservable<Order> ObserveOrders(this IProxy proxy,IEqualityComparer<Order> distinctPerDayComparer ) { return Observable.FromEvent<Order>(ev => proxy.OrderUpdated += ev,ev => proxy.OrderUpdate

示例代码:

   public static IObservable<Order> ObserveOrders(this IProxy proxy,IEqualityComparer<Order> distinctPerDayComparer )
   {
        return Observable.FromEvent<Order>(ev => proxy.OrderUpdated += ev,ev => proxy.OrderUpdated -= ev)
                    .Distinct(distinctPerDayComparer);
   } 

   public class DistinctPerDayComparer : IEqualityComparer<Order>
   {
        public bool Equals(Order o1, Order o2)
        {
            if(o1.Id != o2.Id)
               return false;

            bool isSameDay = o1.Date.Day == o2.Date.Day;
            return isSameDay;
        }            

        public int GetHashCode(Order o)
        {
           return o.Id.GetHashCode();
        }
   }

public class Order
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
} 
不同顺序:

 {id:1,D:'5/25/2016'}-{id:2,D:'5/25/2016'}-{id:1,D:'5/26/2016'}
现在假设这个序列是长时间运行的,实际上从来没有调用过onComplete

Rx是如何管理它的,这样它就不会保存内存中所有不同的元素来进行比较的

我猜它会为管道中的元素保留一些存储空间。但我一直认为,在使用下一项调用onNext之后,该项将被简单地处理


但是,如果它被处理了,当调用Distinct运算符时,Rx为EqualityComparer使用了哪些元素

如果查看Rx源代码,您会发现distinct正在使用哈希集并将值存储在其中。你认为物品被简单地处理掉的假设是不正确的

如果您的订单对象很重,您可以使用keyselector,RX将只在hashset中存储该值

.Distinct(o => Tuple.Create(o.id, o.Date), distinctPerDayComparer);
然后需要更改distinctPerDayComparer

public class DistinctPerDayComparer : IEqualityComparer<Tuple<int, DateTime>>
{
    public bool Equals(Tuple<int, DateTime> o1, Tuple<int, DateTime> o2)
    {
        if(o1.Item1 != o2.Item1)
           return false;

        bool isSameDay = o1.Item2.Day == o2.Item2.Day;
        return isSameDay;
    }            

    public int GetHashCode(Tuple<int, DateTime> o)
    {
       return o.Item1.GetHashCode();
    }
}
公共类DistinctPerDayComparer:IEqualityComparer
{
公共布尔等于(元组o1,元组o2)
{
如果(o1.Item1!=o2.Item1)
返回false;
bool isSameDay=o1.Item2.Day==o2.Item2.Day;
返回日期;
}            
公共int GetHashCode(元组o)
{
返回o.Item1.GetHashCode();
}
}
没有测试代码,但应该是一个起点。现在将存储元组,直到序列完成,而不是存储Order对象


否则,您可以使用窗口功能对它们进行分组,并按计划进行清理,但对于整个可观察序列来说,这并不是完全不同的。

谢谢。我没注意到。主持人是有问题的。我想知道是否有办法每天处理序列中的所有元素。再看一下我的代码,我发现我只为上面的简化示例编写了0。我确实返回了哈希代码。我编辑了这个问题。你可以使用这个窗口使它成为一个每天可观察的。FromEvent(ev=>proxy.OrderUpdate+=ev,ev=>proxy.OrderUpdate-=ev)。窗口(TimeSpan.FromDays(1))。选择(Observable=>Observable.Distinct(distinctPerDayComparer)).Merge();更新的答案为您提供了另一个选项。Distinct将继续收集要比较的值,直到序列完成。它可能不是您想要的工具,或者您需要使用Window、TakeUntil+Repeat完成序列。这将取决于何时可以重新开始收集项目(可能是每天?)我已经按照下面的答案中的建议这样做了。@LeeCampbell很抱歉,在下面的答案中的评论中建议了这一点。我会修改他的答案,把它包括进去
public class DistinctPerDayComparer : IEqualityComparer<Tuple<int, DateTime>>
{
    public bool Equals(Tuple<int, DateTime> o1, Tuple<int, DateTime> o2)
    {
        if(o1.Item1 != o2.Item1)
           return false;

        bool isSameDay = o1.Item2.Day == o2.Item2.Day;
        return isSameDay;
    }            

    public int GetHashCode(Tuple<int, DateTime> o)
    {
       return o.Item1.GetHashCode();
    }
}