Petrroll
Petrroll

Reputation: 761

Can't modify property of a structure stored in a another property

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

Answers (2)

James Michael Hare
James Michael Hare

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

Marc Gravell
Marc Gravell

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

Related Questions