论immutable不可变性
什么叫immutable和mutable?简单来讲,一个immutable的对象一旦被创建好,它的状态将不会改变。反过来,如果一个类的实例是immutable的,那么我们把这个类也称作immutable class。
immutable的优势
- 便于多线程编程
- 方便地作为hashtable的key
- 便于比较状态
说明:本身变化才叫变化,类似string,int(等基元值类型)默认已经是不可变的,如果你修改他们,只是重新分配一个新的而矣。如果是自定义的值类型struct,最好也指定为immutable。
通过readonly来指定。
C#中immutable的实现
经典的immutable class
class Contact
{
public Contact(String fullName, String phoneNumber)
{
this.fullName= fullName;
this.phoneNumber= phoneNumber;
}
public Contact ChangeNumber(String newNumber)
{
//创建一个新实例
return new Contact (this.fullName, newNumber);
}
readonly String fullName;
public String FullName { get { return fullName; }}
readonly String phoneNumber;
public uint PhoneNumber{ get { return phoneNumber; }}
}这个例子几乎无须再解释,每次changeNumber的时候就构造一个新的Contact对象。
C# 对immutability的支持离不开这两个关键字: const和readonly。C#的编译器使用这两个关键字来确保某创建好的对象的状态不会发生改变。之所以提供这两个关键字,自然是因为它们还是有所区别的。readonly允许在构造器中改变它的状态(初始化),而const则不行。例如:
class cnblogs{
Article(string author,string title) { 
a_title= title;
authorName = author; // 编译此处会报错
}
readonly string a_title;
const string authorName = "Freesc";
}
(其他关于readonly和const的讨论,见这里)
现在也许你会问,如果我的对象通过一个readonly的字段引用了另一个对象会怎样呢?被引用的对象的状态会发生改变么?答案是肯定的,看下面的例子:
public class C
{
private static readonly int[] ints = new int[] { 1, 2, 3 };
public static int[] Ints { get { return ints; }
}
这里如果我们尝试在C中改变数组的值:C.ints = null;是无效的操作,这就是一种所谓的“引用不可变”,注意这里只是说引用不可变,如果你尝试在C外部使用:C.Ints[1] = 123;这样的操作,你会发现数组本身其实是可以改变的。我们姑且可以把ints字段称之为“浅”不可变字段。所以你可以相对灵活的指定你需要immutable的字段,可以参考Eric Lippert的文章.
与hashtable的相关性,只有immutable的对象作为hash的键,才能保证hash值始终为常量。当然,通常hash的值是从对象的某些状态(或者子状态)计算而来,而对象的这些状态(子状态)应为immutable。
以下摘取,可以释疑
In Java strings are immutable. If we have a string and make changes to it, we get new string referenced by the same variable:
String str = "abc";
str += "def"; // now str refers to another piece in the heap containing "abcdef"
// while "abc" is still somewhere in the heap until taken by GC
It's been said that int and double are immutable in C#. Does it mean that when we have int and later change it, we would get new int "pointed" by the same variable? Same thing but with stack.
int i = 1;
i += 1; // same thing: in the stack there is value 2 to which variable
// i is attached, and somewhere in the stack there is value 1
Is that correct? If not, in what way is int immutable?
You haven't changed (and cannot change) something about the int; you have assigned a new int value (and discarded the old value). Thus it is immutable.
Consider a more complex struct:
var x = new FooStruct(123);
x.Value = 456; // mutate
x.SomeMethodThatChangedInternalState(); // mutate
x = new FooStruct(456); // **not** a mutate; this is a *reassignment*
However, there is no "pointing" here. The struct is directly on the stack (in this case): no references involved.
论immutable不可变性的更多相关文章
- hashable
Glossary — Python 3.6.5 documentation https://docs.python.org/3/glossary.html?highlight=equal hashab ...
- JAVA不可变类(immutable)机制与String的不可变性--非常好.
JAVA不可变类(immutable)机制与String的不可变性 https://www.cnblogs.com/jaylon/p/5721571.html
- JAVA不可变类(immutable)机制与String的不可变性
一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类, ...
- 【Java基础】JAVA不可变类(immutable)机制与String的不可变性
一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String(8种基本数据类型的包装类和S ...
- 【JDK源码分析】String的存储区与不可变性
// ... literals are interned by the compiler // and thus refer to the same object String s1 = " ...
- Java中String类型的不可变性和驻留池
一 基本概念 可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当获得这个类的一个实例引用时,可以改变这个实例的内容. 不可变类:不可变类的实例一但创 ...
- 多线程程序设计学习(3)immutable pattern模式
Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者 1.1:immutable参与者是一个 ...
- 【JDK源码分析】String的存储区与不可变性(转)
// ... literals are interned by the compiler // and thus refer to the same object String s1 = " ...
- 多线程学习之二坚不可摧模式Immutable pattern
Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者 1.1:immutable参与者是一个 ...
随机推荐
- linux python 图形编程 qt开发环境搭建
我的系统是 ubuntu14.04 我们使用的是python2.7,建议安装qt4+pyqt4+eric4 eric是pyqt的界面设计器的代码生成软件. 1.安装sip 这个是python和qt之间 ...
- scrapy 伪装代理和fake_userAgent的使用
伪装浏览器代理 在爬取网页是有些服务器对请求过滤的不是很高可以不用ip来伪装请求直接将自己的浏览器信息给伪装也是可以的. 第一中方法: 1.在setting.py文件中加入以下内容,这是一些浏览器的头 ...
- <mvc:annotation-driven>注册了什么
前言 上一篇文章dispatcherservlet初始化中提到,如果没有配置handlermapping就会采取默认的策略进行配置handlermapping,这篇文章就要讲述mvc:annotati ...
- mount: /dev/sdb already mounted or /sheepdog1 busy(multipath,wwid,uuid,udev)
正常处理逻辑: 先umount /dev/sdb或是umount /backup如果还是显示的busy,你试试下面的方法fuser -m /dev/sdb查看一下是否sdb1正在被使用,或是有进程正在 ...
- MEF学习总结(4)---Container层
通过AttributeedModelPrograming,我们可以声明暴露组件,依赖组件,发现组件,但是所有这些需要有一个触发点.即需要把所有这些组合在一起来协同工作,最终实现依赖注入.这就是Cont ...
- MEF学习总结(3)---Attribute Model Programing
上一片介绍了Primitive层,Attribute Model可以认为是对Primitive的上层实现.主要包括如下内容: 1. 一系列的Attribute来定义Import和Export 常用的有 ...
- Eclipse编译问题
问题现象:Maven编译ok,Eclipse始终存在编译错误,点了工程的刷新,没用,点了Eclipse上面的菜单Project -> Clean,也没用.后来看了下工作空间项目目录,发现.cla ...
- (转)Inno Setup入门(十七)——Inno Setup类参考(3)
本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17250993 标签(Label)是用来显示文本的主要组件之一,也是窗 ...
- struts2学习(15)struts2防重复提交
一.重复提交的例子: 模拟一种情况,存在延时啊,系统比较繁忙啊啥的. 模拟延迟5s钟,用户点了一次提交,又点了一次提交,例子中模拟这种情况: 这样会造成重复提交: com.cy.action.St ...
- appium+python自动化28-name定位
前言 appium1.5以下老的版本是可以通过name定位的,新版本从1.5以后都不支持name定位了 name定位报错 1.最新版appium V1.7用name定位,报错: selenium.co ...