在表达式体属性中调用新的RelayCommand(ICommand)是否安全 [英] Is it safe to call new RelayCommand (ICommand) in Expression-Bodied Properties

查看:47
本文介绍了在表达式体属性中调用新的RelayCommand(ICommand)是否安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用表达式体属性,我们可以创建RelayCommand,如下所示

public RelayCommand Command => _command ?? (_command = new RelayCommand(CommandExecute));

不过,这也是可能的

public RelayCommand Command => new RelayCommand(CommandExecute);
显然,这会在每次调用属性getter时创建一个新的RelayCommand。尽管我看到的一些评论说底层管道只创建一个命令...

有人对这个问题有明确的答案吗?

推荐答案

有人对这个问题有明确的答案吗?

文档并未承诺只检索一次属性值。因此,您必须假定它可以多次检索它。

当然,在实践中,这种假定的行为可能永远不会发生。如果属性从未发生属性更改通知,则一旦检索到该属性,就再也不会检索该属性,当然,只读属性也永远不会有属性更改通知。

所以你可能可以逃脱惩罚。但就我个人而言,我不会冒险。如果底层实现发生变化,或者您的假设因任何原因而错误,那么拥有同一命令的两个或多个实例将是一个问题,至少在该命令引发CanExecuteChanged事件的情况下是这样。我的意思是,我猜如果CanExecute()状态不变,您可以拥有任意多个对象的副本,并且它们的工作方式完全相同。但是,如果它可以更改,那么您最终可能会在错误的命令对象上引发事件,而这个对象没有人在监听。

这不仅仅是学术问题。Microsoft或某一天可能使用的基于XAML/MVVM的API的其他实现者不仅可以选择放弃存储命令对象引用,而是依赖于始终能够从模型对象中检索它,而且在模型对象本身中从属性中检索命令对象是常见的做法。命令属性被多次读取的情况完全有可能发生,并且值得担心。

更重要的是,我看不到这两个选项背后的动机。"每次都创建一个新的"在我看来显然是错误的,即使你可以逃脱惩罚。而且懒惰的初始化看起来像是没有任何好处的过于复杂的代码。毕竟,在创建模型对象之后,几乎总是发生的下一件事是属性被绑定到UI,因此将在那时检索命令属性。延迟初始化最多会将基础字段的初始化延迟几毫秒(通常比这要短得多)。

如果您放弃了惰性初始化,则可以使用自动属性:

public RelayCommand Command { get; } = new RelayCommand(CommandExecute);

没有显式字段!好多了,我也是。

当然,请注意,要使用该语法,CommandExecute()必须是static成员。大多数命令确实需要访问模型实例,因此上面的命令不适用于这些命令。

lazy-init模式流行的一个原因可能是它允许使用字段初始值设定项语法,作为通常的"不允许在字段初始值设定项中使用实例成员"规则的漏洞。

就我个人而言,我仍然会选择使用当前实例的命令的构造内初始化(这对于只读的自动属性和hellip很好;您仍然不需要显式的支持字段)。在此方案中,lazy-init似乎是不成熟的错误优化。

这篇关于在表达式体属性中调用新的RelayCommand(ICommand)是否安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆