Graviton
Graviton

Reputation: 83306

Automatic Property Value Not Updated with Struct

Take the following struct class:

public struct SingleWraper
{
    private double _myValue;

    public double MyValue
    {
        get { return _myValue; }
        set { _myValue = value; }
    }

    public void SetMyValue(double myValue)
    {
        _myValue = myValue;
    }
}

public struct DoubleWraper
{
    public SingleWraper SingWraper { get; set; }

    public void SetMyValue(double singleVa)
    {
        SingWraper.SetMyValue(singleVa);
    }
}

Run the following test:

    [Test]
    public void SetMyValue()
    {
        var singleWraper = new DoubleWraper();
        singleWraper.SetMyValue(10);
        Assert.AreEqual(10,singleWraper.SingWraper.MyValue);
    }

It fails.

However, if you don't use automatic property for DoubleWraper, i.e, you expand the field as below:

public struct DoubleWraper
{
    private SingleWraper _singWraper;
    public SingleWraper SingWraper
    {
        get { return _singWraper; }
        set { _singWraper = value; }
    }

    public void SetMyValue(double singleVa)
    {
        _singWraper.SetMyValue(singleVa);
    }
}

Then the test will pass.

Why this is so?

Upvotes: 3

Views: 173

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064114

It is here:

_singWraper.SetMyValue(singleVa);

vs:

SingWraper.SetMyValue(singleVa);

In the second, you access a property, therefore you clone the struct; essentially this is the same as:

var clonedAndIndependentValue = SingWraper; // getter
clonedAndIndependentValue.SetMyValue(singleVa);

Note we've updated a different struct value; contrast to field access, which talks to the existing struct value.

Yet another example of why mutable structs are evil. DON'T DO IT. Make the struct immutable (no Set* methods, property setters, or other shenanigans). Or use a class.

Upvotes: 7

Related Questions