Reputation: 749
folks, I've get compilation error('Can not modify the return value of dictionary because it's not a variable') in next code :
public class BaseForm : Form
{
protected void StoreGridViewPosition(DataGridView grid)
{
if (grids.ContainsKey(grid))
{
grids[grid].RowIndex = grid.CurrentCell.RowIndex;
grids[grid].ColumnIndex = grid.CurrentCell.ColumnIndex;
}
Cell s = new Cell();
s.RowIndex = 213;
}
protected void LoadGridViewPosition(DataGridView grid)
{
}
private Dictionary<DataGridView, Cell> grids = new Dictionary<DataGridView, Cell>();
private struct Cell
{
public int RowIndex;
public int ColumnIndex;
}
}
But if i'll replace struct(Cell) with class, then it works fine. Why it happens ?
Upvotes: 1
Views: 297
Reputation: 64477
This won't work as you expect. When you call:
grids[grid].
A copy of the struct is returned from the indexer, not a reference. So when you set into it:
grids[grid].RowIndex = grid.CurrentCell.RowIndex;
You are actually setting into a copy of the struct. This copy is then immediately discarded. All of this behaviour stems from the value type semantics of structs.
All you can do if you use a struct is set a brand new struct into the cell:
grids[grid] = new Cell { RowIndex = 3, ColumnIndex = 1 };
Or pull a copy of the old one and set it back in (ignoring for a moment that structs should really always be made immutable :-) :
var cell = grids[grid];
cell.RowIndex = 3;
grids[grid] = cell;
Changing the definition to a class means the indexer returns a reference to that class, which you can mutate as both your reference and the dictionary's reference are pointing at the same underlying object.
The compiler is saying (in not so many words) that you are inadvertently trying to change a copy of what you think you are changing. You can make the same mistake easily if you expose a struct as a property of a class and try to mutate struct members thus:
myClass.MyPointStruct.X = 2;
(This appears to give the same error message in the new compiler at least, I could have sworn at one point it used to let you do this...)
Or if you cast the struct to an interface, boxing boxes a copy.
This question is very similar:
Modify Struct variable in a Dictionary
Upvotes: 6
Reputation: 6730
When your StoreGridViewPosition calls your Cell, you get a copy of the struct inside. Your call updates the value, and then throws it away (i.e. nothing useful).
Upvotes: 1
Reputation: 9113
struct a value types so when coming from your dictionary, what you get is a copy of the one standing in the dictionary. C# is actually preventing you from having bad surprise...
Upvotes: 0