# ReactivePropertySlim
ReactivePropertySlim is a lightweight version ReactiveProperty.
ReactivePropertySlim is five times faster than ReactiveProperty.
ReactivePropertySlim provides following features:
- Implements
INotifyPropertyChangedinterface. - Implements
IObservable<T>interface. - Provides a
Valueproperty. - Provides a
ForceNotifymethod.
ReactivePropertySlim is high performance.
The following table is a result of the benchmark test between ReactiveProperty and ReactivePropertySlim.
ReactivePropertySlim is 16 times performance to create an instance, 36 times performance on the primary use case.
| Method | Mean | Error | StdDev |
|----------------------------------- |-------------:|----------:|----------:|
| CreateReactivePropertyInstance | 87.146 ns | 0.8331 ns | 0.7385 ns |
| CreateReactivePropertySlimInstance | 5.460 ns | 0.0537 ns | 0.0502 ns |
| BasicForReactiveProperty | 2,470.957 ns | 9.1934 ns | 8.1497 ns |
| BasicForReactivePropertySlim | 68.773 ns | 1.3841 ns | 1.8478 ns |
This class can be used like a ReactiveProperty.
var rp = new ReactivePropertySlim<string>("neuecc");
rp.Select(x => $"{x}-san").Subscribe(x => Console.WriteLine(x));
rp.Value = "xin9le";
rp.Value = "okazuki";
Output is as below.
neuecc-san
xin9le-san
okazuki-san
One difference to ReactiveProperty is that ReactivePropertySlim can't be created from IObservable<T>.
// It isn't valid code.
var rp = Observable.Interval(TimeSpan.FromSeconds(1)).ToReactivePropertySlim();
If you want to create Slim class's instance from IObservable<T>, then use the ToReadOnlyReactivePropertySlim extension method.
var rp = Observable.Interval(TimeSpan.FromSeconds(1)).ToReadOnlyReactivePropertySlim();
# Dispatch to UI thread
ReactivePropertySlim class doesn't dispatch to the UI thread automatically.
If you need this, then use the ReactiveProperty or dispatch to the UI thread explicitly.
var rp = Observable.Interval(TimeSpan.FromSeconds(1))
.ObserveOnUIDispatcher() // dispatch to UI thread
.ToReadOnlyReactivePropertySlim();
# Validation
ValidatableReactiveProperty<T> is a lightweight implementation of IReactiveProperty<T> with validation capabilities. It is designed to provide high performance while offering validation features.
# Example
Here is an example of how to use ValidatableReactiveProperty<T> with a simple validation logic:
var validatableProperty = new ValidatableReactiveProperty<string>(
initialValue: "",
validate: value => string.IsNullOrEmpty(value) ? "Value cannot be empty" : null
);
validatableProperty.Value = "valid"; // No validation error
validatableProperty.Value = ""; // Validation error: "Value cannot be empty"
You can also use ValidatableReactiveProperty<T> with DataAnnotations for more complex validation scenarios:
public class Person
{
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
}
public class PersonViewModel : IDisposable
{
private Person _person = new Person();
public ValidatableReactiveProperty<string> Name { get; }
public PersonViewModel()
{
Name = _person.ToReactivePropertySlimAsSynchronized(x => x.Name)
.ToValidatableReactiveProperty(() => Name, disposeSource: true);
}
public void Dispose()
{
Name.Dispose();
}
}
In this example, the Name property of the Person class is validated using DataAnnotations. The PersonViewModel class synchronizes the Name property with a ValidatableReactiveProperty<string> instance, ensuring that validation rules are applied.
# Performance
ValidatableReactiveProperty<T> offers significant performance improvements over traditional ReactiveProperty<T> with validation. The following benchmark results demonstrate the performance benefits:
| Method | Mean | Error | StdDev |
|---|---|---|---|
| ReactivePropertyValidation | 4,954.138 ns | 93.2171 ns | 107.3490 ns |
| ValidatableReactivePropertyValidation | 704.852 ns | 12.8322 ns | 10.7155 ns |
By using ValidatableReactiveProperty<T>, you can achieve high performance while maintaining robust validation logic in your applications.