Search code examples
c#functiondictionarystructreference

C# struct with out parameter


This is probably very simple stupid question but I just need some help understanding it. I'm storing a struct in a dictionary and I want to grab the struct change some values and then have it update automatically in the dictionary but the behavior is weird.

public struct Test
{
    public int a;
}

public class Tester
{
    public static Dictionary<int, Test> d = new Dictionary<int, Test>();

    public static bool GetTest(int position, out Test test)
    {
        if (d.ContainsKey(position)) {
            test = d[position];
            return true;
        } else {
            test = new Test();
            return false;
        }
    }
}

When I try grabbing a struct from the dict and change values it doesn't update.

        Test n = new Test();
        n.a = 10;
        Tester.d.Add(n.a, n);

        Tester.GetTest(10, out Test t1);
        Debug.Log(t1.a);

        t1.a = 20;

        Tester.GetTest(10, out Test t2);
        Debug.Log(t2.a);

Keeps showing 10. So when I use the out parameter it makes a copy of the struct in the dict and returns that? So I need to write an additional line to update the dictionary again right?

What would be a easy way of grabbing a struct and just updating its value in the dictionary without adding additional lines?

EDIT:

I could do this...

Tester.d[position].a = 20;

But is there a way to do that with a method? Where I can get the whole struct, edit a value, and it updates in the dictionary automatically? Sorry for the stupid question, i just dont understand the behaviour.


Solution

  • You should not do that. While it is possible to change the value inside of a struct, even if the value is nested in a dictionary (such as in your example), you should try to avoid that and consider structs read-only. If you want to update a value of a dictionary, replace the entire value with a new instance instead of manipulating its contents. Chances are big the behavior is otherwise not what you'd expect.

    The performance impact of doing a replacement should be minimal, too. So you can do

    Tester.d[position] = new Test() { a = 20 };