什么叫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#连接数据库以及增、删、改、查操作

    using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; usin ...

  2. Sprint第一个冲刺(第八天)

    一.Sprint介绍 完善点餐界面,点击进行跳转. 实验截图: 任务进度: 二.Sprint周期 看板: 燃尽图:

  3. systemtap 安装试用

    1. 安装 yum install -y systemtap systemtap-runtime 2. 环境准备    a. 自动安装依赖 stap-prep b. 手动安装依赖 kernel-deb ...

  4. 从汇编的角度看待变量类型与sizeof的机制

    1.动机:前段时间,一直有个疑问,就是编译器是从哪里知道数据的类型的,数据的类型是存在内存里面的么,因为自己调试编译器,发现内存中并没有多余的数据,后来在群上发问,才知道数据在编译成汇编的过程就知道数 ...

  5. laravel的phpstorm插件laravel-ide-helper

    地址https://github.com/barryvdh/laravel-ide-helper 简单记录下安装过程 项目目录下 composer require barryvdh/laravel-i ...

  6. js实现定时调用的函数setInterval()

    setInterval是一个实现定时调用的函数,可按照指定的周期(以毫秒计)来调用函数或计算表达式.setInterval方法会不停地调用函数,直到 clearInterval被调用或窗口被关闭 定义 ...

  7. linux性能监控——CPU、Memory、IO、Network

    一.CPU 1.良好状态指标 CPU利用率:User Time <= 70%,System Time <= 35%,User Time + System Time <= 70%. 上 ...

  8. bzoj4764: 弹飞大爷

    Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小 ...

  9. python稀疏矩阵得到每列最大k项的值,对list内为类对象的排序(scipy.sparse.csr.csr_matrix)

    print(train_set.tdm) print(type(train_set.tdm)) 输出得到: (0, 3200) 0.264940780338 (0, 1682) 0.356545827 ...

  10. 使用wifi网卡笔记5---AP模式

    使用WIFI网卡的AP功能 1.下载源码 hostapd: http://w1.fi/hostapd/ 2.编译.安装(hostapd依赖于libnl库,需要编译.安装此库) tar xzf host ...