Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify Struct variable in a Dictionary

I have a struct like this:

public struct MapTile {     public int bgAnimation;     public int bgFrame; } 

But when I loop over it with foreach to change animation frame I can't do it...

Here's the code:

foreach (KeyValuePair<string, MapTile> tile in tilesData) {         if (tilesData[tile.Key].bgFrame >= tilesData[tile.Key].bgAnimation)         {             tilesData[tile.Key].bgFrame = 0;         }         else         {             tilesData[tile.Key].bgFrame++;         } } 

It gives me compile arror:

Error 1 Cannot modify the return value of 'System.Collections.Generic.Dictionary<string,Warudo.MapTile>.this[string]' because it is not a variable Error 2 Cannot modify the return value of 'System.Collections.Generic.Dictionary<string,Warudo.MapTile>.this[string]' because it is not a variable 

Why can't I change a value inside a struct which is inside a dictionary?

like image 471
NewProger Avatar asked Jun 06 '11 16:06

NewProger


People also ask

Can struct values be changed?

Unlike classes, a constant struct's properties cannot be changed—not from outside the struct, not even from within the struct's own methods, even if they're marked as mutating . Once a struct is constant, it is constant. It can't change.

Is it possible to use a custom struct as a dictionary key?

Is it possible to use a custom struct as a dictionary key in Swift? Any type that conforms to the Hashable protocol can be used as a dictionary's Key type, including all of Swift's basic types. You can use your own custom types as dictionary keys by making them conform to the Hashable protocol.

Can a dictionary hold different data types?

One can only put one type of object into a dictionary. If one wants to put a variety of types of data into the same dictionary, e.g. for configuration information or other common data stores, the superclass of all possible held data types must be used to define the dictionary.

Is struct same as dictionary?

Their intent tends to be different, as revealed by their names: structs are for structured collections of data, while dictionaries are for long lists of named elements. [ The internal workings are certainly different, but the point of this post is that this paragraph on internals is a digression which you can skip.


1 Answers

The indexer will return a copy of the value. Making a change to that copy won't do anything to the value within the dictionary... the compiler is stopping you from writing buggy code. If you want to do modify the value in the dictionary, you'll need to use something like:

// Note: copying the contents to start with as you can't modify a collection // while iterating over it foreach (KeyValuePair<string, MapTile> pair in tilesData.ToList()) {     MapTile tile = pair.Value;     tile.bgFrame = tile.bgFrame >= tile.bgAnimation ? 0 : tile.bgFrame + 1;     tilesData[pair.Key] = tile; } 

Note that this is also avoiding doing multiple lookups for no good reason, which your original code was doing.

Personally I'd strongly advise against having a mutable struct to start with, mind you...

Of course, another alternative is to make it a reference type, at which point you could use:

// If MapTile is a reference type... // No need to copy anything this time; we're not changing the value in the // dictionary, which is just a reference. Also, we don't care about the // key this time. foreach (MapTile tile in tilesData.Values) {     tile.bgFrame = tile.bgFrame >= tile.bgAnimation ? 0 : tile.bgFrame + 1; } 
like image 67
Jon Skeet Avatar answered Sep 29 '22 03:09

Jon Skeet