Reputation: 761
I have a little problem, I can't modify property of structure that is stored in another property and I have no idea why:
Code:
public struct InfoProTile
{
public string Nazev { get; set; }
public double Hodnota { get; set; }
public TypValue TypValue { get; set; }
public NavigovatNa NavigovatNa { get; set; }
}
public InfoProTile BNDTileInfo { get { return bndTileInfo; } set { bndTileInfo = value; } } private InfoProTile bndTileInfo;
LoadModel()
{
...
BNDTileInfo = new InfoProTile();
BNDTileInfo.NavigovatNa = NavigovatNa.MainPage;
}
Error:
Error: Error 3 Cannot modify the return value of '...ViewModel.TilesModel.BNDTileInfo' because it is not a variable
I don't get it because if I just change it into:
bndTileInfo.NavigovatNa = NavigovatNa.MainPage;
It works. Can anyone please explain it to me?
Upvotes: 3
Views: 162
Reputation: 38397
A struct
is a value type, thus when you access it from a property, you are getting back a copy of the struct
and not the underlying field direclty. Thus, C# won't let you modify that copy of the struct because that is just a temporary object that will be discarded.
So, when you call:
BNDTitleInfo.NavigovatNa = ...;
It first calls the get
on the property and returns a copy of bndTitleInfo
, and then attempts to set the NavigovatNa
property and the copy. C# gives you the error here because that is not something you really want to do and thus is protecting you from yourself.
But, when you call:
bndTitleInfo.NavigovatNa = ...;
You are referencing the field directly and thus no copy is made and there is no compiler issue.
The long and the short of it is that mutable value types don't make good properties (and in general you should avoid mutable value types completely).
To rectify, you can either make it a reference type (class
) or you can make your struct
immutable, which would mean you'd have to assign a whole new struct instance to change it's value.
If you look at MSDN's recommendations, in general struct
is best suited to small, logical-single-value, immutable constructs: Choosing Between Classes and Structures
Upvotes: 7
Reputation: 1062770
Because BNDTileInfo
is a property, you get a clone of the data. And changes to a clone are lost when it is discarded, i.e. your code is:
var tmp = BNDTileInfo; // tmp is a completely separate clone
tmp.NavigovatNa = NavigovatNa.MainPage; // change the local clone
// discard the clone - our change was wasted
the compiler has stopped you getting a big problem. This is because of what struct
means, i.e. value-type semantics, aka copy semantics.
The real answer here is: don't make that a struct
. Even without knowing what any of those words are, I am 99% sure that should not be a struct
. Of course, I'd still be 98.5% sure it shouldn't be a struct
even if you'd just said "I have a struct
called InfoProTile
".
Make BNDTileInfo
a class
, unless you can explain very clearly why it is a struct
, and can then justify why it is a mutable struct
.
Upvotes: 7