Search code examples
c#dictionaryreferenceouttrygetvalue

c#: Dictionary TryGetValue creating instance instead of getting reference


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?


Solution

  • 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();