# ReactivePropertySlim
ReactivePropertySlim
is a lightweight version ReactiveProperty
.
ReactivePropertySlim
is five times faster than ReactiveProperty
.
ReactivePropertySlim
provides following features:
- Implements
INotifyPropertyChanged
interface. - Implements
IObservable<T>
interface. - Provides a
Value
property. - Provides a
ForceNotify
method.
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.