我写了下面的扩展方法:
public static void NotifyChanged<T>(this INotifyPropertyChanged inpc, ref T current, T newValue, Action<PropertyChangedEventArgs> eventRaiser, [CallerMemberName] string? name = null) where T : IEquatable<T> {
if (current.Equals(newValue)) { return; }
current = newValue;
eventRaiser(new PropertyChangedEventArgs(name));
}
可以这样使用:
public class Foo : Bar, INotifyPropertyChanged {
public event PropertyChangedEventHandler? PropertyChanged;
private string? rootExpression;
public string? RootExpression {
get => rootExpression;
set => this.NotifyChanged(ref rootExpression, value, args => PropertyChanged?.Invoke(this, args));
}
}
这节省了大量编写 INPC 感知属性的样板文件。
但是,我现在在调用 NotifyChanged
时收到编译器警告错误:
The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'INotifyPropertyChangedExtensions.NotifyChanged(INotifyPropertyChanged, ref T, T, Action, string?)'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable'.
AFAICT 错误是说 string?
无法转换为 IEquatable<string?>
, 只有 string
可以转换为 IEquatable<string>
.
我该如何解决这个问题?应用一些属性?还是别的?
最佳答案
你的问题是:
where T : IEquatable<T>
这表示 T
必须是不可为 null 的 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
.
如果current
,这也解决了您的 NRE 问题是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);
关于c# - 参数的可空性与约束类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60668629/