如果分配相同的值,setter 是否应该立即返回?
在实现 INotifyPropertyChanged 的类中,我经常看到这种模式:
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
正是这些线条
if (value == _customer.FirstName)
return;
困扰着我。我经常这样做,但我不确定它是否需要或不好。毕竟,如果调用者分配了完全相同的值,我不想重新分配该字段,特别是通知我的订阅者该属性已更改,但从语义上看,它没有更改。
除了通过使 UI 免于更新在屏幕/无论什么媒介上看起来可能相同的内容来节省一些 CPU/RAM/等之外,我们还能得到什么?
有些人是否可以通过在属性上重新分配相同的值来强制刷新(但这并不是一个好的做法)?
1.我们应该这样做还是不应该这样做?
2.为什么?
In classes that implement INotifyPropertyChanged I often see this pattern :
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
Precisely the lines
if (value == _customer.FirstName)
return;
are bothering me. I've often did this but I am not that sure it's needed nor good. After all if a caller assigns the very same value I don't want to reassign the field and, especially, notify my subscribers that the property has changed when, semantically it didn't.
Except saving some CPU/RAM/etc by freeing the UI from updating something that will probably look the same on the screen/whatever_medium what do we obtain?
Could some people force a refresh by reassigning the same value on a property (NOT THAT THIS WOULD BE A GOOD PRACTICE HOWEVER)?
1. Should we do it or shouldn't we?
2. Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,当消费者设置的属性值等于已保存的值时,您应该立即返回。
首先,没有理由在属性的设置器中浪费任何时间或资源 - 值已经设置,因此不需要进一步的操作。此外,如果存储在属性支持字段中的值未更改,则永远不应该调用
OnPropertyChanged
- 该方法旨在在值发生更改时引发,而不是在属性发生变化时引发。设置器已被调用。尽管如此,如果 setter 没有调用 OnPropertyChanged,我就不会先检查该值。对于仅设置支持字段的值而不设置其他值的简单设置器,实际上始终设置值比先检查然后设置值会更快。仅当属性的 setter 具有不应触发或可能导致不必要的性能损失的附加逻辑时,才使用此模式。
Yes, you should return immediately when the consumer is setting a property value that is equal to the value which is already being persisted.
First of all, there is no reason to waste any time or resources in the setter of the property - the value is already set so no further action is needed. Also you should never call
OnPropertyChanged
if the value stored in the property's backing field hasn't changed - the method is intended to be raised when the value has changed not when the property's setter has been called.All that being said, however - if the setter didn't have a call to
OnPropertyChanged
I wouldn't have bothered to check the value first. In the case of a simple setter that only sets the backing field's value and nothing else it is actually going to be faster to always the set the value rather than checking first then setting the value. Only use this pattern when the property's setter has additional logic that either shouldn't fire or may incur an unnecessary performance penalty.或者您可以这样做:
不需要多个返回路径。
为了进一步回答您的问题,如果属性被相同的值覆盖,我不会强制更新属性。这确实没有意义,因为您可能不会从中获得任何好处。 (我可以看到一个实例,您希望在每次有人尝试更新值时进行跟踪。)
Or you could do this:
No need for multiple return paths.
To further answer your question, I wouldn't force an update to property if it's being overwritten by the same value. There's really no point, because you're probably not going to get any benefit from it. (I could see an instance where you would want to track each time someone tries to update a value.)
我能想到的反对该模式的唯一论据(如果值没有改变则返回)是纯粹主义者的观点,即每个函数应该只有一个出口。作为一个纯粹主义者,我不同意。如果值没有改变,我认为打破并避免通知更新没有任何问题。
The only argument against that pattern (where you return if the value hasn't changed) I can think of is the purist's view that every function should have only one exit. Not being a purist, I don't agree. I see nothing wrong with breaking out if the value hasn't changed, avoiding the notification update.
不应该使用它的唯一情况是当您知道类上可能有脏数据时,例如在可能具有过时值的 ORM 层对象上由于另一个用户的修改而与底层数据库进行比较。
如果这种情况对你没有影响,那就缓存起来吧!
编辑
我误解了你的问题,因为你正在谈论setters,而不是getters。
类似点也适用。如果设置操作的成本很高,并且不应该有任何副作用(它不应该!对设置器的副作用是
邪恶< /em>
!!1),那么这是一个有效的优化。
The only situation when you shouldn't use it is when you know that you can have dirty data on your class, for example on a ORM layer object that might have outdated values compared to the underlying database because of modification by another user.
If that situation doesn't affect you, then cache away!
Edit
I misunderstood your question, as you are talking about setters, not getters.
Similar points apply. If the set operation is a costly one, and is not supposed to have any kind of side effect (it should't! Side effects on setters are
<blink>
evil</blink>
!!1), then it's a valid optimization.我想,不早回来的原因之一是迟到的订户。他们可能不知道对象的当前状态,并且如果您提前返回,就会错过 setter 通知。
One reason to not return early, I would imagine, is for subscribers that joined the party late. They might not be aware of the object's current state, and will miss out on the setter notification if you return early.
大多数时候这些属性用于绑定。但是,一旦您自己开始使用
NotifyPropertyChanged
事件(在自己的标记扩展、行为、MVVM 中的 VM 之间等),您就会意识到您只是希望此事件始终发生。对我来说,这种检查(通知保护)是一种过早的优化。我经常使用
""
作为propertyName
来引发事件,以刷新绑定或强制某些自定义内容的事件,仅此一项的成本就高得多。我认为没有必要保护每项财产。为什么?来自什么样的操作?动画在依赖属性上运行。用户更新(当视图绑定更新源时)无论如何都很慢。对于从代码后面引发的任何更新,您几乎需要事件才能引发。
对我来说,它看起来像是一种模式,毫无理由地发明并盲目遵循。当然,在某些情况下,您需要阻止属性设置器代码在某些条件下运行。如果您添加此类检查来解决某些性能问题,那就没问题了。但不是提前。
Most of times those properties are used in binding. But as soon as you start using
NotifyPropertyChanged
event yourself (in own markup extenstions, behaviors, between VM in MVVM, etc.) you will realise you just want this event to always occurs.To me this check (notification protection) is kind of premature optimization. I am often rising event with
""
aspropertyName
to just refresh bindings or force event for some custom stuff and that alone is much more costly.I don't see a need to protect each property. Why? From what kind of operation? Animations are running on dependency properties. User updates (when view bindings are updating source) are anyway slow. And for any update rised from within code behind you are pretty much need event to be rised.
To me it looks like a pattern, invented without much reasons and followed blindly. Of course there are cases when you need to prevent property setter code from being running under certain conditions. And that's ok if you add such checks to solve certain performance issue then. But not in advance.