Reputation: 81711
I originally took it from this address: http://csharpindepth.com/articles/chapter8/propertiesmatter.aspx and for some reason I could not get my head around it. Can somebody explain me why Console.WriteLine(holder.Property.Value); outputs 0.
void Main()
{
MutableStructHolder holder = new MutableStructHolder();
holder.Field.SetValue(10);
holder.Property.SetValue(10);
Console.WriteLine(holder.Field.Value); // Outputs 10
Console.WriteLine(holder.Property.Value); // Outputs 0
}
struct MutableStruct
{
public int Value { get; set; }
public void SetValue(int newValue)
{
Value = newValue;
}
}
class MutableStructHolder
{
public MutableStruct Field;
public MutableStruct Property { get; set; }
}
Upvotes: 0
Views: 86
Reputation: 21742
When you are accessing the property of holder you are creating a copy of the original struct and then calling the method SetValue
on the copy.
The below code would functionally do the same
//First create a copy of the original
var property = new MutableStruct();
property.Value = holder.Property.Value;
//That's not how the copy is actually created but the result is the same
//set the value on the copy
property.SetValue(10);
//print the value of the original
Console.WriteLine(holder.Property.Value);
this happens for properties because properties are essentially methods. When you call the get method a copy of the original is created and it's the copy that's returned by the method not the original
Upvotes: 1
Reputation: 103437
class MutableStructHolder
{
public MutableStruct Field;
public MutableStruct Property { get; set; }
}
Is equivalent to
class MutableStructHolder
{
public MutableStruct Field;
private MutableStruct _Property;
public MutableStruct Property {
get { return _Property; }
set { _Property = value; }
}
}
Which is equivalent to:
class MutableStructHolder
{
public MutableStruct Field;
private MutableStruct _Property;
public MutableStruct getProperty() {
return _Property;
}
public void setProperty(MutableStruct value) {
_Property = value;
}
}
So, when you do this:
holder.Property.SetValue(10);
You're actually doing this:
holder.getProperty().SetValue(10);
Which is equivalent to:
MutableStruct temp = holder.getProperty();
temp.SetValue(10);
And because structs are value types, temp
is actually a copy of the underlying _Property
field, and your modification is thrown away when it goes out of scope (immediately).
This is a good reason to avoid mutable structs like the plague.
Upvotes: 4
Reputation: 840
The comment in the linked code explains this...
Retrieves holder.Property as a copy and changes the copy
In other words, the .SetValue(10)
on holder.Property
applies to a copy of holder.Property
, not holder.Property
itself.
Upvotes: 1
Reputation: 12849
This is because structs are value types and when you pass it around it creates a copies. With field, you are accessing the real version of the structure, while with property, it returns it's copy. You then change this copy and the copy is then thrown away.
Upvotes: 1