rx.net中是否有功能类似于BehaviorSubject的Subject实现,但仅在值发生更改时才发出? [英] Is there a Subject implementation in Rx.NET that functionally resembles BehaviorSubject but emits only if the value has changed?

查看:23
本文介绍了rx.net中是否有功能类似于BehaviorSubject的Subject实现,但仅在值发生更改时才发出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

rx.net中是否有Subject实现在功能上类似于BehaviorSubject,但仅在其发生更改时才发出下一个值?

我对反应式扩展相当陌生,似乎找不到任何类似的东西,尽管此模式感觉像是INotifyPropertyChanged的自然替代品。

我的简单实现是封装BehaviorSubject<T>,如下所示。与使用Observable.DistinctUntilChanged创建可组合的可观察对象相比,这样做有什么缺点吗?

    public class DistinctSubject<T> : SubjectBase<T>
    {
        private readonly BehaviorSubject<T> _subject;

        public DistinctSubject(T initialValue) =>
            _subject = new BehaviorSubject<T>(initialValue);

        public T Value 
        { 
            get => _subject.Value;
            set => this.OnNext(value);
        }

        public override bool HasObservers => _subject.HasObservers;

        public override bool IsDisposed => _subject.IsDisposed;

        public override void Dispose() => _subject.Dispose(); 

        public override void OnCompleted() => _subject.OnCompleted();   

        public override void OnError(Exception error) => _subject.OnError(error);

        public override void OnNext(T value)
        {
            if (!EqualityComparer<T>.Default.Equals(value, _subject.Value))
            {
                _subject.OnNext(value);
            }
        }

        public override IDisposable Subscribe(IObserver<T> observer) =>
            _subject.Subscribe(observer);
    }

推荐答案

浏览了一下BehaviorSubject<T>类的source code之后,如果OnError后跟OnNext

,您的DistinctSubject<T>实现的行为似乎会有所不同
var subject = new DistinctSubject<int>(2021);
subject.OnError(new ApplicationException());
subject.OnNext(2022); // throws ApplicationException

此操作将引发,而对BehaviorSubject<T>执行相同操作将不会引发(仅忽略OnNext)。

我的建议是在实现中使用DistinctUntilChanged运算符,如下所示:

public class DistinctSubject<T> : ISubject<T>, IDisposable
{
    private readonly BehaviorSubject<T> _subject;
    private readonly IObservable<T> _distinctUntilChanged;

    public DistinctSubject(T initialValue, IEqualityComparer<T> comparer = default)
    {
        _subject = new BehaviorSubject<T>(initialValue);
        _distinctUntilChanged = _subject.DistinctUntilChanged(
            comparer ?? EqualityComparer<T>.Default);
    }

    public T Value => _subject.Value;
    public void OnNext(T value) => _subject.OnNext(value);
    public void OnError(Exception error) => _subject.OnError(error);
    public void OnCompleted() => _subject.OnCompleted();

    public IDisposable Subscribe(IObserver<T> observer) =>
        _distinctUntilChanged.Subscribe(observer);

    public void Dispose() => _subject.Dispose();
}

如果您担心对象的不必要分配,那么您还不熟悉Rx的精神。此库关注的是功能和易用性,而不是performance或效率!

这篇关于rx.net中是否有功能类似于BehaviorSubject的Subject实现,但仅在值发生更改时才发出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆