不可变数据的设计与使用:
当我们设计一个struct名叫Address,它当中有数组时,尽管将set方法删除,如下操作还能更改原数组的源数据
struct Address
{
string city;
string province;
string zip;
string[] phones;
public Address(string province, string city, string zip, string[] phones)
{
this.city = city;
this.province = province;
this.zip = zip;
this.phones = phones;
}
//数组属性
public string[] Phones
{
get { return phones; }
}
}
static void Main(string[] args)
{
string[] phones = { "029-88401100", "029-88500321" };
Address a = new Address("陕西", "西安", "710068", phones);
Console.WriteLine(a.Phones[0]); // 输出: 029-88401100
string[] b = a.Phones;//因为指向的是同一个地址,所以B里面的数据改变,A里面的数据也会改变
b[0] = "029-XXXXXXXX"; // 通过b修改了 Address的内容
Console.WriteLine(a.Phones[0]);
Console.ReadLine();
}
输出为:
当我们将get方法声明了一个新的数组,再使用上面的方法,这样就不会改变源数据了。
public string[] Phones
{
get {
string[] rtn = new string[phones.Length];
phones.CopyTo(rtn,0);
return rtn;
}
}
更新以后输出为:
但是,我们还有一个问题,我们更改源数据时,源数据数组是可以被改变的,示例如下:
string[] phones = { "029-88401100", "029-88500321" };
Address a = new Address("陕西", "西安", "710068", phones);
Console.WriteLine(a.Phones[0]); // 输出: 029-88401100
phones[0] = "029-XXXXXXXX"; // 通过phones变量修改了Address对象内部的数据
Console.WriteLine(a.Phones[0]); // 输出: 029-XXXXXXXX
输出为:
通过上面的问题,可以思考,如果我们在构造函数里面进行深度复制,那么这样源数据就不会被更改了,示例如下:
public Address(string province, string city, string zip, string[] phones)
{
this.city = city;
this.province = province;
this.zip = zip;
//this.phones = phones;
this.phones = new string[phones.Length];//属性phones被赋值的是新的
//一个数组,而不是外面传进来的数组,这样改变原来的数组也不会改变成员属性数组
phones.CopyTo(this.phones, 0);
}
输出如下: