gpt4 book ai didi

c# - Rx.NET "gate"运算符

转载 作者:行者123 更新时间:2023-12-03 21:50:40 25 4
gpt4 key购买 nike

[注意:如果重要的话,我正在使用 3.1。另外,我在 codereview 上问过这个问题,但到目前为止还没有回复。]

我需要一个运算符来允许 bool 值流充当另一个流的门(当门流为真时让值通过,当门流为假时丢弃它们)。我通常会使用 Switch 来实现此目的,但如果源流很冷,它会继续重新创建它,这是我不希望的。

我还想自己清理,以便在源或门完成时结果也完成。

public static IObservable<T> When<T>(this IObservable<T> source, IObservable<bool> gate)
{
var s = source.Publish().RefCount();
var g = gate.Publish().RefCount();

var sourceCompleted = s.TakeLast(1).DefaultIfEmpty().Select(_ => Unit.Default);
var gateCompleted = g.TakeLast(1).DefaultIfEmpty().Select(_ => Unit.Default);

var anyCompleted = Observable.Amb(sourceCompleted, gateCompleted);

var flag = false;
g.TakeUntil(anyCompleted).Subscribe(value => flag = value);

return s.Where(_ => flag).TakeUntil(anyCompleted);
}

除了整体冗长之外,我不喜欢订阅门,即使结果从未订阅(在这种情况下,该运算符应该是无操作)。有没有办法摆脱订阅?

我也尝试过这种实现,但是当涉及到自身清理时,情况更糟:

return Observable.Create<T>(
o =>
{
var flag = false;
gate.Subscribe(value => flag = value);

return source.Subscribe(
value =>
{
if (flag) o.OnNext(value);
});
});

这些是我用来检查实现情况的测试:

[TestMethod]
public void TestMethod1()
{
var output = new List<int>();

var source = new Subject<int>();
var gate = new Subject<bool>();

var result = source.When(gate);
result.Subscribe(output.Add, () => output.Add(-1));

// the gate starts with false, so the source events are ignored
source.OnNext(1);
source.OnNext(2);
source.OnNext(3);
CollectionAssert.AreEqual(new int[0], output);

// setting the gate to true will let the source events pass
gate.OnNext(true);
source.OnNext(4);
CollectionAssert.AreEqual(new[] { 4 }, output);
source.OnNext(5);
CollectionAssert.AreEqual(new[] { 4, 5 }, output);

// setting the gate to false stops source events from propagating again
gate.OnNext(false);
source.OnNext(6);
source.OnNext(7);
CollectionAssert.AreEqual(new[] { 4, 5 }, output);

// completing the source also completes the result
source.OnCompleted();
CollectionAssert.AreEqual(new[] { 4, 5, -1 }, output);
}

[TestMethod]
public void TestMethod2()
{
// completing the gate also completes the result
var output = new List<int>();

var source = new Subject<int>();
var gate = new Subject<bool>();

var result = source.When(gate);
result.Subscribe(output.Add, () => output.Add(-1));

gate.OnCompleted();
CollectionAssert.AreEqual(new[] { -1 }, output);
}

最佳答案

更新:当门终止时,此操作也会终止。我在复制/粘贴中错过了 TestMethod2:

    return gate.Publish(_gate => source
.WithLatestFrom(_gate.StartWith(false), (value, b) => (value, b))
.Where(t => t.b)
.Select(t => t.value)
.TakeUntil(_gate.IgnoreElements().Materialize()
));

这通过了 您的测试 TestMethod1,当门可观察到时它不会终止。

public static IObservable<T> When<T>(this IObservable<T> source, IObservable<bool> gate)
{
return source
.WithLatestFrom(gate.StartWith(false), (value, b) => (value, b))
.Where(t => t.b)
.Select(t => t.value);
}

关于c# - Rx.NET "gate"运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50666864/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com