Reputation: 83306
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
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