2

I'm a total noob with c#, and cannot figure out why the same method works in different ways. I'm making a simple spreadsheet application, and am using a Dictionary of cells, where the key is a string name and the value is a Cell object:

public struct Cell
{
    private string Name { get; }
    public Object Content { get; set; }

    public Cell(string n, Object o)
    {
        Name = n;
        Content = o;
    }
}

Now, I'll need to be able to easily add/change the contents of the cell, so I've been doing this:

Dictionary<string, Cell> cells = new Dictionary<string, Cell>();

//  Assign new cell to 5.0 & print
cells.Add("a1", new Cell("a1", 5.0));
Console.WriteLine(cells["a1"].Content);     //  Writes 5

//  Assign cell to new content & print
cells.TryGetValue("a1", out Cell value);
value.Content = 10.0;
Console.WriteLine(cells["a1"].Content);     //  Writes 5
Console.ReadKey();

Of course, the dictionary creates the new cell just fine, but when I use TryGetValue, the new content for the cell doesn't make it to the actual object I'm trying to get. I was expecting the second print to be 10. In debug, it seems like it instantiates a new Cell instead of getting the reference of the cell at hand.

I've used a Dictionary before, and I've used TryGetValue to change properties of the existing object. So here's two questions: What am I doing wrong in this case, and what factors determine if the method returns a reference or not?

  • 1
    You defined Cell as a struct. – Anthony Pegram Feb 16 '18 at 20:11
  • 1
    [structs](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/structs) are value types. So you will retrieve a copy instead of the reference – Link Feb 16 '18 at 20:13

2 Answers2

3

Cell is a struct. It is not recommended that you use a struct for objects that can be modified. I think you just found out why.

When TryGetValue returns the struct, it copies it into a value, which is a different struct than the one in the Dictionary.

Imagine if you replaced struct by int - another value type - would you expect assigning to the int from TryGetValue to change the Dictionary entry int?

If other constraints require you use a struct, you will need to update the cells Dictionary with the new struct, just as you would with any other value type:

Dictionary<string, Cell> cells = new Dictionary<string, Cell>();

//  Assign new cell to 5.0 & print
cells.Add("a1", new Cell("a1", 5.0));
Console.WriteLine(cells["a1"].Content);     //  Writes 5

//  Assign cell to new content & print
cells.TryGetValue("a1", out Cell value);
value.Content = 10.0;
cells["a1"] = value;  // update cells Dictionary
Console.WriteLine(cells["a1"].Content);     //  Writes 5
Console.ReadKey();
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • Perfect, when I replaced 'struct' with 'class', it met my expectations. I guess the real problem here is that, per my professor's specifications, Cell is to be a struct. I suppose I could change the Dictionary to be (where Object is the cell's contents), but wouldn't that just eliminate the need for a Cell struct in the first place? Any insight? – crapolantern Feb 16 '18 at 20:21
1

You need to make your struct Cell into a class Cell.

That's because struct is a value type and it's content can't be changed by reference. If you want to go in detail, you can read about difference of value and reference types here.

Glitch
  • 42
  • 9