CommunityToolkit.Mvvm 8.0.0-preview4 RelayCommand CanExecute报错
CommunityToolkit.Mvvm 8.0.0-preview4 中 RelayCommand CanExecute 可空参数编译错误原因
这个报错是8.0.0-preview4预览版自带的源生成器缺陷,和业务代码逻辑无关。
该版本内置的Roslyn源生成器在校验CanExecute方法和命令方法的签名匹配度时,没有兼容C#可空引用类型的编译期注解规则:它会将带可空标注的string?和不带标注的string判定为完全不同的参数类型,哪怕两个方法的参数同步加了可空标注,也会被校验逻辑误判为签名不兼容,触发MVVMTK0011错误。
错误提示中文翻译:error MVVMTK0011: CanExecute 配置的名称必须对应一个签名兼容的成员,但当前类型中未找到与"CanDo"匹配的有效成员
不同写法的编译表现
- 参数使用非可空
string类型时,源生成器可以正常完成签名匹配,代码可正常编译运行:
public bool CanDo(string x) => true; [RelayCommand(CanExecute = nameof(CanDo))] public void DoSomething(string x){}
- 两个方法的参数同步修改为可空
string?类型时,源生成器校验逻辑异常,直接抛出编译错误:
public bool CanDo(string? x) => true; [RelayCommand(CanExecute = nameof(CanDo))] public void DoSomething(string? x){}
可行解决方法
可以根据实际项目情况选择任意一种方案绕开问题:
- 升级到8.0.0正式版及更高版本,该可空参数匹配bug在正式发布版本中已经修复,原有可空参数的代码不需要做任何修改即可正常编译
- 若暂时无法升级依赖版本,可以移除CanExecute方法参数上的可空标注,只要两个方法的参数运行时类型一致,仅去掉CanExecute的可空注解不会影响可空参数的正常传入,也不会破坏可空类型的校验逻辑:
// 仅移除CanDo方法参数的?标注,即可通过preview4版本的编译校验 public bool CanDo(string x) => true; [RelayCommand(CanExecute = nameof(CanDo))] public void DoSomething(string? x){}
- 如果CanExecute判断逻辑不需要读取命令传入的参数,可以直接写无参版本的CanExecute方法,该写法在所有版本的源生成器中都能正常匹配:
public bool CanDo() => true; [RelayCommand(CanExecute = nameof(CanDo))] public void DoSomething(string? x){}
内容的提问来源于stack exchange,提问作者Nadir Mezhoudi
相关产品推荐
相关产品推荐

