How to swap property values in ViewModel? Can't pass by ref

474 Views Asked by At

I'd like to compare and swap the values of two ViewModel public properties, ideally using a method like this:

void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
    T temp;
    if (lhs.CompareTo(rhs) > 0)
    {
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}

But as you can't pass properties by ref, I can't do this in my ViewModel.

private Int32 max;
public Int32 Max
{
    get { return max; }
    set
    {
        SwapIfGreater<Int32>(ref Min, ref Max);
        max = value;
        OnPropertyChanged("Max");
    }
}

private Int32 min;
public Int32 Min
{
    get { return min; }
    set
    {
        SwapIfGreater<Int32>(ref Min, ref Max);
        min = value;
        OnPropertyChanged("Min");
    }
}

Failing that... if I just try to use the "if compare" logic directly within the Min getter or setter, when Min is changed to a value greater than Max, I just end up with Min equal to Max.

EDIT: Based upon the advice about backing properties I've amended the method to this:

void SwapIfGreater<T>(ref T lhs, ref T rhs, String otherPropertyName) where T : System.IComparable<T>
{
    T temp;
    if (lhs.CompareTo(rhs) > 0)
    {
        temp = lhs;
        lhs = rhs;
        rhs = temp;
        OnPropertyChanged(otherPropertyName);
    }            
}

and the "Min" Property setter to this:

    min = value;
    SwapIfGreater<Int32>(ref min, ref max, "Max");                
    OnPropertyChanged("Min");

What am I missing? This is still just setting Max to Min when Min is greater than Max.

EDIT: Although I'm keen to learn what I'm doing wrong above, having tested the UI again which implements the swap behaviour I wanted to replicate, I've realised it's a nasty UX, as the user is force to then click both pickers again. I'm going to revert to my original implementation of resetting Max to "No Maximum" if the user selects a Min higher than Max and vice versa.

2

There are 2 best solutions below

2
On BEST ANSWER

You can not pass properties by ref because properties are translated to getter and setter methods.

Use the backing fields of properties instead

SwapIfGreater<Int32>(ref min, ref max);
0
On

When you pass a parameter as ref ,its Address it passed. A property looks like a value, buts it's actually a pair of functions, each with a different signature. So to pass a property, you actually need to pass two function pointers, one for the get, and one for the set.

This is a completely different thing to pass to a function than the address of a variable

i.e. one variable address v's two function pointers.

So, try to avoid pass properties as Ref or Out.

Dotctor has provided you correct solution.

SwapIfGreater<Int32>(ref min, ref max);