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 (da开发者_如何学运维d2.Equals (dad1) + " " + dad1.sons.Count () + " " + dad2.sons.Count ());
//true 2 2
}
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
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
精彩评论