13.2 结构是值类型
对于类而言,两个变量指向同一个对象的情况是存在的,因此对这样两个变量中的任意一个进行操作,其结果必然会影响另一个,因为它们指向的是同一个对象。这种情况对于结构而言是不可能发生的,结构是值类型,直接包含它自己的数据,每个结构都保存自己的一份数据,修改每一个结构的数据都不会对其他结构的数据造成影响。
如果从结构创建一个对象,并将该对象赋给某个变量,则该变量包含结构的全部值。复制类型为结构的变量时,将同时复制该结构所持有的所有数据。因此,对新副本所做的任何修改都不会对旧副本的数据产生影响。另外需要注意的是,由于结构不是引用类型,因此结构类型的变量不能被赋予null值。
接下来使用一段代码进行说明。首先定义两个类型:
❑结构类型:AddressBookEntry;
❑类:AddressBookEntryClass。
它们具有相同的字段成员:Name、MobilePhone、Birthday。在Main函数中,先定义两个AddressBookEntry类型的变量:entry和entry2,先对entry进行赋值,赋完值后将entry变量赋给entry2变量,然后对entry2的值进行修改,注意观察是否会影响到entry的值。
接下来,再定义两个AddressBookEntryClass类型的变量:entry3和entry4,步骤同上,对entry3赋值后再将entry3赋给entry4,然后对entry4的值进行修改,观察结果,如代码清单13-3所示。
代码清单13-3 结构是值类型
1 public struct AddressBookEntry//定义一个结构类型
2{
3 public string Name;
4 public string MobilePhone;
5 public DateTime Birthday;
6}
7
8 public class AddressBookEntryClass//定义一个类
9{
10 public string Name;
11 public string MobilePhone;
12 public DateTime Birthday;
13}
14
15 public class StructSample
16{
17 public static void Main()
18{
19 AddressBookEntry entry,entry2;//声明两个结构类型的变量
20 entry.Name="Tom";//赋值
21 entry.MobilePhone="1234567";
22 entry.Birthday=DateTime.Parse("2000-1-1 12:12:12");
23
24//将entry赋给entry2,然后修改entry2,注意观察看是否会
25//影响entry的数据
26 entry2=entry;
27 entry2.Name="Jerry";
28 entry2.MobilePhone="7654321";
29 entry2.Birthday=DateTime.Parse("2010-1-1 10:10:10");
30
31 AddressBookEntryClass entry3,entry4;
32 entry3=new AddressBookEntryClass();
33 entry3.Name="Tom";
34 entry3.MobilePhone="1234567";
35 entry3.Birthday=DateTime.Parse("2000-1-1 12:12:12");
36
37//将entry3赋给entry4,然后修改entry4,注意观察看是否会
38//影响entry的数据
39 entry4=entry3;
40 entry4.Name="Jerry";
41 entry4.MobilePhone="7654321";
42 entry4.Birthday=DateTime.Parse("2010-1-1 10:10:10");
43
44 System.Console.WriteLine(“姓名:{0} 手机:{1} 生日:{2}”,entry.Name,entry.MobilePhone,entry.Birthday);
45 System.Console.WriteLine(“姓名:{0} 手机:{1} 生日:{2}”,entry2.Name,entry2.MobilePhone,entry2.Birthday);
46
47 System.Console.WriteLine(“姓名:{0} 手机:{1} 生日:{2}”,entry3.Name,entry3.MobilePhone,entry3.Birthday);
48 System.Console.WriteLine(“姓名:{0} 手机:{1} 生日:{2}”,entry4.Name,entry4.MobilePhone,entry4.Birthday);
49}
50}
上述代码的运行结果为:
姓名:Tom 手机:1234567 生日:2000-1-1 12:12:12
姓名:Jerry 手机:7654321 生日:2010-1-1 10:10:10
姓名:Jerry 手机:7654321 生日:2010-1-1 10:10:10
姓名:Jerry 手机:7654321 生日:2010-1-1 10:10:10
从结果可以看出,对entry2值的修改并未影响到entry的值,而对entry4的修改让entry4和entry3的值变得相同,这说明每个结构类型存储的都是自己的数据,在将一个结构类型的变量赋给另一个结构类型的变量的时候,CLR执行的是将数据复制过去的策略。而类则不同,类是引用类型,entry3和entry4保存的都是指向数据对象的引用,并且它们指向的是同一个对象,因此对entry4的修改也对entry3的数据产生了直接的影响。我们使用图示进行说明,如图13-1所示。
图 13-1 结构是值类型