什么叫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的支持离不开这两个关键字: constreadonly。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不可变性的更多相关文章

  1. hashable

    Glossary — Python 3.6.5 documentation https://docs.python.org/3/glossary.html?highlight=equal hashab ...

  2. JAVA不可变类(immutable)机制与String的不可变性--非常好.

    JAVA不可变类(immutable)机制与String的不可变性 https://www.cnblogs.com/jaylon/p/5721571.html

  3. JAVA不可变类(immutable)机制与String的不可变性

    一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类, ...

  4. 【Java基础】JAVA不可变类(immutable)机制与String的不可变性

    一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String(8种基本数据类型的包装类和S ...

  5. 【JDK源码分析】String的存储区与不可变性

    // ... literals are interned by the compiler // and thus refer to the same object String s1 = " ...

  6. Java中String类型的不可变性和驻留池

    一 基本概念 可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当获得这个类的一个实例引用时,可以改变这个实例的内容. 不可变类:不可变类的实例一但创 ...

  7. 多线程程序设计学习(3)immutable pattern模式

    Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者        1.1:immutable参与者是一个 ...

  8. 【JDK源码分析】String的存储区与不可变性(转)

    // ... literals are interned by the compiler // and thus refer to the same object String s1 = " ...

  9. 多线程学习之二坚不可摧模式Immutable pattern

    Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者        1.1:immutable参与者是一个 ...

随机推荐

  1. C#.NET抽象类和接口的区别?

    声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况.不能创建abstract 类的实例.然 ...

  2. MVC之前的那点事儿 ---- 系列文章

    MVC之前的那点事儿系列,是笔者在2012年初阅读MVC3源码的时候整理的,主要讲述的是从HTTP请求道进入MVCHandler之前的内容,包括了原创,翻译,转载,整理等各类型文章,当然也参考了博客园 ...

  3. odoo10 修改产品单价的小数点位数

    odoo10 修改产品单价的小数点位数 由于产品价格原因,单价需要保留小数点后 5 位,所以需要修改单价的小数点位数. 开启开发模式 找到数据库编辑 找到小数点精度 修改产品的小数点位数

  4. 使用cookie纪录访问次数

    由于是简单的demo,我就没有链接数据库,退出重新登陆访问次数清零,只能靠下刷新来维持下访问次数 把用户名和次数初始化放进cookie Cookie uesrnameCookie = new Cook ...

  5. python 与时间有关的操作

    python保存时间戳文件 import time # ISOTIMEFORMAT='%Y-%m-%d %X' ISOTIMEFORMAT='%Y-%m-%d' t= time.strftime( I ...

  6. ffmpeg/ffplay 添加实时的时间水印 (转)

    右上角添加时间水印 ffmpeg -i 0.ts -vf drawtext="fontfile=arial.ttf:x=w-tw:fontcolor=white:fontsize=30:te ...

  7. spring装载配置文件失败报错:org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException

    Tomcat容器启动失败,找到 debug日志一看: Context initialization failed org.springframework. beans.factory.xml.XmlB ...

  8. java web 程序--注册页面/HashMap的用法。。要懂啊

    思路:1.一个form表单,用户输入后,提交 2.第二个是注册页面,主要是用Map.先假设往map里面拿东西,然后判断是否为空  若为空,new 一个HashMap它的子类,然后通过map.conta ...

  9. Druid.io系列(二):基本概念与架构

    原文链接:  https://blog.csdn.net/njpjsoftdev/article/details/52955788 在介绍Druid架构之前,我们先结合有关OLAP的基本原理来理解Dr ...

  10. 自己个儿写的循环分配txt中的内容

    <?php header("Content-type:text/html;charset=utf8"); //当前日期 $now = time(); //作为程序是否执行的依 ...