1

http://ideone.com/U0XFO9

Why is the property directly set outputting the expected number and the property indirectly set equaling the last set number? Apologies for all the code but this is a boiled down version of the actual code.

The following code outputs:

1 // 9
2 // 9
3 // 9
4 // 9
5 // 9
6 // 9
7 // 9
8 // 9
9 // 9

When it should output:

1 // 1
2 // 2
3 // 3
4 // 4
5 // 5
6 // 6
7 // 7
8 // 8
9 // 9

Code

using System;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        int x = 0;

        example original_example = new example(0);

        List<example> examples = new List<example>();

        while (++x < 10)
        {
            examples.Add(new example(original_example, x));
        }

        foreach(example _example in examples)
            Console.WriteLine(_example.number1 + " // " + _example.number2);

    }

    public class example
    {
        public int number1;
        public int number2 { get { return (int)values["number"]; } }
        public bool original = true;

        Dictionary<string, object> values = new Dictionary<string,object>();

        public example(int number)
        {
            original = true;
            number1 = number;
            values.Add("number", number);
        }

        public example(example original_example, int number)
        {
            original = false;
            values = original_example.values;
            values["number"] = number;
            number1 = number;
        }
    }
}
iambriansreed
  • 21,935
  • 6
  • 63
  • 79
  • you're sharing the dictionary instance from the original_example when you do "values = original_example.values", so there's a single dictionary with a single value for all objects. – fsimonazzi Dec 12 '13 at 19:38

1 Answers1

1

The issue is here: values = original_example.values;

We assign the memory address of a reference type Dictionary<string, object> to a new variable that points to the same address in memory. Any updates made to this new variable impact the same object.

Instead, to achieve the desired result copy the dictionary. This can be done by creating a new Dictionary and passing the original into the cstor:

        public example(example original_example, int number)
        {
            original = false;
            values = new Dictionary<string, object>(original_example.values);//Copy
            values["number"] = number;
            number1 = number;
        }

MSDN has more information on the topic of reference types. Also see the related subject reference types vs value types.

Community
  • 1
  • 1
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
  • +1 Thank you. I had no idea I was modifying the original. So strange. This works fine and already tested it. But is there an alternative to this? – iambriansreed Dec 12 '13 at 19:43
  • 1
    @iambriansreed - You are working with a copy of the value of a reference type which is just an address in memory. So you are modifying the same object. I'm not sure what kind of alternative you are looking for? What's the issue with the solution? – P.Brian.Mackey Dec 12 '13 at 19:45
  • Thanks again. I am confused by the reference issues. Any documentation you can point me at? – iambriansreed Dec 12 '13 at 19:49
  • 1
    @iambriansreed Jon Skeet and Eric Lippert have several excellent breakdowns on the subject. One place to start: http://stackoverflow.com/questions/5057267/what-is-the-difference-between-a-reference-type-and-value-type-in-c – P.Brian.Mackey Dec 12 '13 at 19:52