Ваша проблема:
where T : IEquatable<T>
Это говорит о том, что T
должен быть не обнуляемым IEquatable<T>
. Вы хотите, чтобы это было обнуляемым. Вы можете сказать это, добавив ?
:
where T : IEquatable<T>?
Обратите внимание, что тогда будет выдан запрос на if (current.Equals(newValue))
, который выдаст, если current
равен null
.
Обычный способ сделать это не ограничить T
быть IEquatable<T>
, а использовать EqualityComparer<T>.Default
. Если T
реализует IEquatable<T>
, это дает вам средство сравнения равенства, которое вызывает IEquatable<T>.Equals
, в противном случае он возвращается к вызову обычного object.Equals
.
. Это также решает вашу проблему NRE, если current
is null
:
public static void NotifyChanged<T>(
this INotifyPropertyChanged inpc,
ref T current, T newValue,
Action<PropertyChangedEventArgs> eventRaiser,
[CallerMemberName] string? name = null)
{
if (EqualityComparer<T>.Default.Equals(current, newValue)) { return; }
current = newValue;
eventRaiser(new PropertyChangedEventArgs(name));
}
Также редко передается eventRaiser
: обычно вы делаете NotifyChanged
метод в базовом классе, который реализует INotifyPropertyChanged
, а не делая это методом расширения. Затем вы можете просто позволить NotifyChanged
вызвать событие PropertyChanged
или написать другой метод, например OnPropertyChanged
, который вызывает PropertyChanged
, и вызывать его из NotifyChanged
.
Если вы хотите передать в случае, чтобы поднять, вы можете просто передать в PropertyChangedEventHandler
:
public static void NotifyChanged<T>(
this INotifyPropertyChanged _,
ref T current, T newValue,
PropertyChangedEventHandler eventHandler,
[CallerMemberName] string? name = null)
{
if (EqualityComparer<T>.Default.Equals(current, newValue)) { return; }
current = newValue;
eventHandler?.Invoke(this, new PropertyChangedEventArgs(name));
}
this.NotifyChanged(ref rootExpression, value, PropertyChanged);