繁体   English   中英

在表达式绑定的属性中调用新的RelayCommand(ICommand)是否安全?

[英]Is it safe to call new RelayCommand (ICommand) in Expression-Bodied Properties

通过表达式的属性,我们可以创建一个RelayCommand ,如下所示

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

但是,这也是可能的

public RelayCommand Command => new RelayCommand(CommandExecute);

显然,这在每次调用属性getter都会创建一个新的RelayCommand。 尽管有评论我说周围的管道仅创建一个命令...

有人对此有明确的答案吗?

有人对此有明确的答案吗?

该文档不保证只检索一次属性值。 因此,您必须假定它可以多次检索它。

当然,实际上,这种假定的行为可能永远不会发生。 完全有道理的是,如果某个属性从未发生过属性更改的通知,则一旦检索到该属性,就永远不会再次检索该属性,当然,只读属性也不会具有属性更改的通知。

因此,您可能可以摆脱它。 但就我个人而言,我不会冒险。 如果基础实现发生了变化,或者由于某种原因您的假设是错误的,那么至少有一个命令引发CanExecuteChanged事件的情况下,使用同一命令的两个或多个实例将是一个问题。 我的意思是,我想如果CanExecute()状态永远不会改变,那么您可以根据需要拥有任意数量的对象副本,并且它们的工作原理完全相同。 但是,如果它可以更改,则可能导致在错误的命令对象上引发该事件,而没人在听。

这不只是学术上的。 Microsoft或您的代码有一天可能会与Microsoft或基于XAML / MVVM的API的某些其他实现者一起使用,选择放弃存储命令对象引用,而是指望始终能够从模型对象中检索它,它不仅可以在模型对象本身中的常见做法是从属性中检索命令对象。 多次读取命令属性的情况是完全合理的,值得担心。

更重要的是,我看不到任何一种选择背后的动机。 即使您可以摆脱困境,“每次都创建一个新的”似乎对我来说显然是错误的。 惰性初始化似乎过于复杂,没有任何好处。 毕竟,在创建模型对象之后,几乎总是发生的下一件事是将属性绑定到UI,因此将在那时检索command属性。 延迟初始化最多会将基础字段的初始化延迟毫秒(通常比这要少得多)。

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

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

没有明确的领域! 更好,恕我直言。

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

惰性初始化模式流行的一个可能原因是它允许使用字段初始化程序语法,这是对通常的“不允许在字段初始化程序中使用实例成员”规则的漏洞。

就我个人而言,对于使用当前实例的命令,我仍然会选择构造函数内初始化(这对于只读自动属性很好,但是您仍然不需要显式的后备字段)。 在这种情况下,惰性初始化似乎是过早错误的优化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM