【问题标题】:If you're binding to an object with read-only properties, should you still implement INotifyPropertyChanged?如果要绑定到具有只读属性的对象,是否仍应实现 INotifyPropertyChanged?
【发布时间】:2019-01-17 16:53:34
【问题描述】:

在为我们正在开发的某些组件编写 API 时,我们需要公开一些只读 POCO 对象,用户可以(并且很可能会)在他们的应用程序中为其创建数据模板,因此他们将使用绑定到它们。

现在我知道你可以绑定到直接 POCO 对象(即不是DependencyObject 的子类),即使它们没有实现INotifyPropertyChanged,但是当你这样做时,除非你明确地将这些绑定标记为一次性,否则你'正在创建对您的对象的不必要引用并可能暴露内存泄漏。

摘自this article

[...] 这有 2 个含义,此操作会导致公共语言运行时 (CLR) 创建从该 PropertyDescriptor 对象到对象 X 的强引用。CLR 还在全局表中保留对 PropertyDescriptor 对象的引用.

现在,虽然我们可以尝试记录对这些对象的所有绑定都应该是一次性的,但这会给消费者带来负担。我想知道无论如何只实现INotifyPropertyChanged 是否有意义,尽管没有任何改变专门用于防御性地解决内存泄漏。

换句话说,哪个更重,绑定到 POCO 属性而不使用一次性,还是防御性地实现 INotifyPropertyChanged

这样做有什么坏处吗?虽然不像一次性绑定那样轻量级,但它仍然必须比消费者将它们设置为一次性所产生的效果更好。

如果有什么不同,那么只有一百个左右,所以这是一个非常小的集合。

【问题讨论】:

  • 我很欣赏它们可能不那么优雅,但您可能需要考虑实现只读依赖属性。这样就不需要实现INotifyPropertyChanged
  • 实现 INotifyPropertyChanged 然后从不触发其 PropertyChanged 事件有什么好处? CLR 将仍然创建并保留对 PropertyDescriptor 的引用。所以你的问题的答案很明显:“不,你不应该”。
  • @Bijington,你不能在 POCO 上实现依赖属性。它必须是DependencyObject 的子类,如果是,则此问题不适用。
  • @Clemens,是的,还有一个参考,但它的成本比不实现接口的对象要小得多,因此我的问题是。
  • 我不明白,不管有没有 INPC,都会保留参考。那么好处在哪里呢?

标签: wpf data-binding binding poco inotifypropertychanged


【解决方案1】:

这样做有什么坏处吗?

如果有的话,缺点应该可以忽略不计。显然有一个非常小的内存损失。除了您需要在 POCO 类中定义 PropertyChanged 事件之外,WPF 还将订阅它,这将根据您的 CPU 架构分配额外的 4 或 8 个字节。但这并不是不实现接口的真正正当理由。

因此,如果您担心内存泄漏并知道并非所有与类属性的绑定都将定义为OneTime,那么将接口实现为对此的保护并没有什么坏处。您可能想在代码中留下注释,说明为什么尽管事件从未引发,但仍实现了接口。

【讨论】:

  • 您永远无法确定您的 API 的使用者会做什么! :) #防御性编程
  • 实际上,多亏了这里其他人的恶作剧 cmets,我从 Microsoft 抓取了一篇博客文章,显示在绑定到非 INPC POCO 时实际上存在内存泄漏(他错误地指出没有't),并且它特别指出“数据绑定中涉及的任何内容都应实现 INotifyPropertyChanged。如果您不是特别喜欢它,则不必引发 PropertyChanged 事件,但为了避免泄漏,您必须实现接口。 "所以你去吧! :) blogs.msdn.microsoft.com/micmcd/2008/03/07/…
  • 好吧,与其盲目相信某人在 2008 年的一篇博文中所写的内容,我建议编写一个小测试程序,看看问题是否仍然存在。我做到了,而且我无法观察到即使是最小的内存泄漏,同时不断地创建和删除绑定到未实现 INotifyPropertyChanged 的​​类中的视图模型属性(在 Windows 10 上使用 .NET 4.7.2)。我没有阅读过去十年的所有 WPF 发行说明,但可能他们只是修复了它。毕竟,虽然没有太大的伤害,但毫无理由地实施 INPC 似乎毫无意义,至少现在是这样。
猜你喜欢
  • 2013-04-15
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
相关资源
最近更新 更多