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();
}
}