不变性的真正定义?

Joa*_*nge 8 .net c# immutability

我想知道如何定义不变性?如果这些值没有公开,那么无法修改,那就够了吗?

是否可以在类型内修改值,而不是类型的客户?

或者只能在构造函数中设置它们?如果是这样,在双初始化的情况下(this在结构上使用关键字等)对于不可变类型仍然可以吗?

我怎样才能保证类型是100%不可变的?

Joe*_*orn 23

如果这些值没有公开,那么无法修改,那就够了吗?

不,因为您需要读取权限.

是否可以在类型内修改值,而不是类型的客户?

不,因为那仍然是突变.

或者只能在构造函数中设置它们?

丁丁丁!另外一点是,不可变类型通常具有构造和返回新实例的方法,并且通常还具有internal专门标记为由这些方法使用的额外构造函数.

我怎样才能保证类型是100%不可变的?

在.Net中获得这样的保证是很棘手的,因为你可以使用反射来修改(变异)私有成员.

  • 几乎涵盖了一切;-p (2认同)

Fre*_*örk 7

之前的海报已经声明你应该在构造函数中为你的字段赋值,然后把它们放在手上.但这有时说起来容易做起来难.假设您的不可变对象公开了该类型的属性List<string>.该列表是否允许更改?如果没有,你将如何控制它?

Eric Lippert在他的博客中撰写了一系列关于C#不变性的帖子,你可能会感兴趣:你在这里找到了第一部分.

  • 这取决于您所暴露的类型的exaclty.使用List <T>,你不能但是如果你公开了一个ReadOnlyCollection <T>你可能(我不太了解它声称保证只读).但是常规数组也是可变的,所以你真的需要注意你在不可变类型中暴露的类型. (4认同)

Mic*_*urr 5

我认为在所有这些答案中可能遗漏的一件事是,我认为即使内部状态发生变化,对象也可以被认为是不可变的 - 只要这些内部变更对'客户'代码不可见.

例如,System.String该类是不可变的,但我认为允许缓存实例的哈希代码,因此哈希仅在第一次调用时计算GetHashCode().需要注意的是,据我所知,System.String类并没有做到这一点,但我认为它可能仍然被认为是不可改变的.当然,任何这些更改都必须以线程安全的方式处理(与更改的不可观察方面一致).

说实话,我想不出有很多可能需要或者需要这种"看不见的可变性"的原因.

  • 一个例子:展开树木.内部突变纯粹用于提高查找性能,但客户端代码无法判断是否发生了突变(当然,也可以实现splay树的可变实现.) (2认同)