简体   繁体   中英

Can binding to a struct's property cause memory leaks in WPF?

Consider the following struct and class :

public struct DemoStruct
{
    public DemoStruct(int value)
    {
        Value = value;
    }
    
    public int Value {get; }
}


public class DemoClass : INotifyPropertyChanged
{
    private DemoStruct _demo;
    public DemoStruct Demo 
    {
        get => _demo;
        set {_demo = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Demo)); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

And, assuming the DataContext is an instance of DemoClass , consider this binding:

<Label Content="{Binding Demo.Value}"/>

By now I've learned that binding to an object that is not a DependencyObject or does not implement INotifyPropertyChanged can cause a memory-leak, see eg Why does implementing INotifyPropertyChanged avoid memory leaks in WPF? .

What I'm wondering is how WPF will handle binding to a struct property.

My DemoStruct does not implement INotifyPropertyChanged , because it is an immutable struct.

I'm assuming it will be boxed by WPF, but will this also create a memory leak, due to the "strong reference" to the boxed struct instance?

And, since a new box will be created whenever WPF accesses the property - will these all leak?

And, a follow up to be on the safe side:

If I were to change the binding to:

<Label Content="{Binding Demo}"/>

Despite the boxing, this should not cause a leak, because WPF does not have to attach any event handlers to "Demo" - right?

Short answer is yes, they can do. Unless you use mode=.netime bindings.

https://learn.microsoft.com/en-us/do.net/api/system.windows.data.bindingmode?view=windowsdesktop-7.0

The struct itself will not cause memory leaks.

Properties on that struct would do.

Demo is a property in a class that implements Inotifypropertychanged. If you bound to Demo then that would not cause a leak but you get a struct. That might not be terribly useful.

If you bind to Demo.Value then that's a property on a struct and that will cause a hard reference to be created. Unless....

Since Demo is to be immutable then maybe in your use case you could try a .netime binding. That doesn't then care about any property changing.

https://learn.microsoft.com/en-gb/archive/blogs/jgoldb/finding-memory-leaks-in-wpf-based-applications

If you switch out Demo then you could consider a converter to read the data out value. Bind to Demo and use a converter which would then read Value and return that. Might be a bit clunky if you had more than one property.

You could alternatively wrap Demo.Value with another property in your viewmodel. Raise propertychanged on wrapper property when demo changes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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