While writing the API for some components we're developing, we have a need to expose some read-only POCO objects which the user can (and most likely will) create data templates for in their app, thus they will be using bindings to them.
Now I know that you can bind to straight POCO objects (i.e. not subclassed of DependencyObject
) even if they don't implement INotifyPropertyChanged
but when you do, unless you explicitly mark those bindings as one-time, you're creating unnecessary references to your objects and potentially exposing memory leaks.
Excerpt from this article:
[...] This has 2 implications, this action causes the common language runtime (CLR) to create a strong reference from this PropertyDescriptor object to object X. The CLR also keeps a reference to the PropertyDescriptor object in a global table.
Now while we can try and document that all bindings to these objects should be one-time, that puts the burden on the consumer. I'm wondering if it makes sense to just implement INotifyPropertyChanged
anyway, even though nothing ever changes specifically to defensively address the memory leaks.
In other words, which is heavier, binding to a POCO property without using one-time, or implementing INotifyPropertyChanged
defensively?
Is there any down-side to doing so? While not as lightweight as one-time bindings, it still has to be better than the effect caused by a consumer not setting them to one-time.
If it makes any difference, there will only be a hundred or so of these so a very small set.
Is there any down-side to doing so?
The downside if any should be negligible. There is obviously a very minor memory penalty. Besides that you need to define the PropertyChanged
event in your POCO class, WPF will also subscribe to it and this will allocate an extra 4 or 8 bytes depending on your CPU architecture. But this is not really a valid reason no to implement the interface.
So if you are concerned about memory leaks and know for a fact that not all bindings to your class' properties will be defined as OneTime
, it does no harm to implement the interface as a guard for this. You may want to leave a comment in the code that mentions why the interface is implemented despite the event never being raised.