关闭

探索C#之不可变数据类型

发表于:2015-9-06 09:09

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:蘑菇先生    来源:51Testing软件测试网采编

  不可变对象
  不可变(immutable): 即对象一旦被创建初始化后,它们的值就不能被改变,之后的每次改变都会产生一个新对象。
  var str="mushroomsir";
  str.Substring(0, 6)
  c#中的string是不可变的,Substring(0, 6)返回的是一个新字符串值,而原字符串在共享域中是不变的。另外一个StringBuilder是可变的,这也是推荐使用StringBuilder的原因。
  var age=18;
  当存储值18的内存分配给age变量时,它的内存值也是不可以被修改的。
  age=2;
  此时会在栈中开辟新值2赋值给age变量,而不能改变18这个内存里的值,int在c#中也是不可变的。
  class Contact
  {
  public string Name { get;  set; }
  public string Address { get;  set; }
  public Contact(string contactName, string contactAddress)
  {
  Name = contactName;
  Address = contactAddress;
  }
  }
  var mutable = new Contact("二毛", "清华");
  mutable.Name = "大毛";
  mutable.Address = "北大";
  我们实例化MutableContact赋值给mutable,随后我们可以修改MutableContact对象内部字段值,它已经不是初始后的值,可称为可变(mutable)对象。
  可变对象在多线程并发中共享,是存在一些问题的。多线程下A线程赋值到 Name = “大毛” 这一步,其他的线程有可能读取到的数据就是:
  mutable.Name == "大毛";
  mutable.Address == "清华";
  很明显这样数据完整性就不能保障,也有称数据撕裂。我们把可变对象更改为不可变对象如下:
  public class Contact2
  {
  public string Name { get; private set; }
  public string Address { get; private set; }
  private Contact2(string contactName, string contactAddress)
  {
  Name = contactName;
  Address = contactAddress;
  }
  public static Contact2 CreateContact(string name, string address)
  {
  return new Contact2(name, address);
  }
  }
  使用时只能通过Contact2的构造函数来初始化Name和Address字段。Contact2此时即为不可变对象,因为对象本身是个不可变整体。通过使用不可变对象可以不用担心数据完整性,也能保证数据安全性,不会被其他线程修改。
31/3123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号