Jesse
Jesse

Reputation: 1402

C++/CX ^ versus &

I'm learning C++/CX by building a windows store app. For the base of my viewmodels I use the standard BindableBase class and added a convenient SetProperty method to it (which I'm used to in my C# projects).

Now I expected I should write it like this:

public ref class BindableBase : Windows::UI::Xaml::DependencyObject, Windows::UI::Xaml::Data::INotifyPropertyChanged,
{        
public:
    virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;   

protected:
    virtual void OnPropertyChanged(Platform::String^ propertyName);

private protected:
    template <typename T>
    bool SetProperty(T^ storage, T^ value, String^ propertyName)
    {
        if (storage == value)
        {
            return false;
        }
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
};

But that doesn't work, the view won't update. But when I changed the signature of the SetProperty method to this:

bool SetProperty(T& storage, T& value, String^ propertyName)

It suddenly does work, but I can't figure out why the ^ syntax doesn't work.

Upvotes: 1

Views: 658

Answers (1)

Rob Caplan - MSFT
Rob Caplan - MSFT

Reputation: 21899

The C++/Cx-isms here aren't the issue. You'll get the same behaviour if you use standard C++ variables as you do using C++/Cx handles (^).

The issue is value parameters vs. reference parameters. By default C++ passes arguments by value. Changes made to the argument are local to the called function and don't affect the caller. If you mark the parameter with an & then the parameter is passed by reference and changes do affect the caller.

This may be clearer if you rewrite the whitespace in your arguments:

bool SetProperty(T &storage, T &value, String ^propertyName)

When you don't use the & syntax you receive the caller's T storage (which must be a ref class, since you used ^) and then overwrite that locally. If you break in the debugger you'll see that storage gets set as you'd like, but step out and compare it in the caller to see the caller's storage is unchanged. Remove the ^s--SetProperty(T storage, T value, String^ propertyName)--and it will act the same with non-ref classes.

When you use the & syntax you receive a reference to the caller's T storage, so changes to storage store value in the caller's variable.

Upvotes: 1

Related Questions