Question

So I found out today that structs and classes act differently when used to assign to variables in C#.. It's to my understanding that when I assign a struct to a variable, the variable stores a copy of that struct, and when I assign a class to a variable, the variable stores the reference to that class instance.

In this case, dad2 contains a copy of dad1, so shouldn't anything I do to dad2 not affect dad1? It's not the case apparently because when I add a son to dad2 it also adds the same son to dad1.

public struct Dad {
        public string name;
        public List <Son> sons;

        public struct Son {
            public string name;

            public Son (string n) {
                name = n;
            }
        }
    }

    static void Main (string [] args) {
        Dad dad1 = new Dad ();
        dad1.name = "Bob";
        dad1.sons = new List <Dad.Son> {new Dad.Son ("A")};

        Dad dad2 = dad1;
        Debug.WriteLine (dad2.Equals (dad1) + " " + dad1.sons.Count () + " " + dad2.sons.Count ());
        //true 1 1
        dad2.sons.Add ( new Dad.Son ("B"));
        Debug.WriteLine (dad2.Equals (dad1) + " " + dad1.sons.Count () + " " + dad2.sons.Count ());
        //true 2 2
    }
Was it helpful?

Solution

yes it makes a copy of the values inside the struct - and inside the struct there a reference to a List so that reference gets copied too - that is a "shallow copy"... if the List would have been copied over to a new object this would be a "deep copy"... Struct assignment uses "copy" semantics which depends the copy semantics of each member... see http://msdn.microsoft.com/en-us/library/saxz13w4.aspx

OTHER TIPS

Think of class-type variables and fields as holding "instance ID's" and everything will be clear. Suppose a struct field "Foo" of type List has a value of "Instance ID#95341". Copying the struct will yield another struct whose field "Foo" also holds "Instance ID#95341". Calling Foo.Add on one such struct will add an element to the list referred to by "Instance ID #95341". Querying Foo.Count on the other such struct will get the count from the list referred to by "Instance ID #95341", which will naturally be the same List.

I am answering to this

so shouldn't anything I do to dad2 not affect dad1?"

With your code, any change in the

public List <Son> sons;

is seen in both copies (dad1 and dad2); however any change in

public string name;

is seen only on the object changed

Example - change only the name of dad2 and not the name of dad1

Dad dad1 = new Dad();
dad1.name = "Bob";
dad1.sons = new List<Dad.Son> { new Dad.Son("A") };

Dad dad2 = dad1;
Console.WriteLine(dad2.Equals(dad1) + " " + dad1.sons.Count() + " " + dad2.sons.Count());
//true 1 1
dad2.sons.Add(new Dad.Son("B"));
Console.WriteLine(dad2.Equals(dad1) + " " + dad1.sons.Count() + " " + dad2.sons.Count());
//true 2 2

dad2.name = "Tom";
Console.WriteLine(dad2.Equals(dad1) + " " + dad1.sons.Count() + " " + dad2.sons.Count());
//False 2 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top