公共只读字段用于不可变的结构是否工作?

这是一个正确的方式来声明不可变的结构?

public struct Pair { public readonly int x; public readonly int y; // Constructor and stuff } 

我想不出为什么会遇到问题,但我只是想问一下。

在这个例子中,我使用了整数。 如果我使用了一个类,但是这个类也是不可变的,像这样呢? 那应该也可以,对不对?

 public struct Pair { public readonly (immutableClass) x; public readonly (immutableClass) y; // Constructor and stuff } 

(另外:我明白,使用属性是更通用的,并允许更改,但是这个结构的意图只是存储两个值,我只是对这个不变性问题感兴趣。

如果你打算使用结构,最好的做法是使它们不可变。

使所有的字段只读是一个很好的方法来帮助(1)certificate结构是不可变的,(2)防止意外突变。

不过,这里有一个皱纹,实际上我下周正在计划一个奇怪的巧合。 那就是: 在struct字段上只读是一个谎言 。 人们期望只读字段不能改变,但当然可以。 在结构字段上的“只读”是在帐户中没有金钱的声明书写检查。 一个结构体并不拥有它的存储空间,而这个存储空间是可以改变的。

例如,让我们拿你的结构:

 public struct Pair { public readonly int x; public readonly int y; public Pair(int x, int y) { this.x = x; this.y = y; } public void M(ref Pair p) { int oldX = x; int oldY = y; // Something happens here Debug.Assert(x == oldX); Debug.Assert(y == oldY); } } 

有什么可以发生在“这里发生的事情”,导致debugging断言被违反? 当然。

  public void M(ref Pair p) { int oldX = this.x; int oldY = this.y; p = new Pair(0, 0); Debug.Assert(this.x == oldX); Debug.Assert(this.y == oldY); } ... Pair myPair = new Pair(10, 20); myPair.M(ref myPair); 

现在会发生什么? 这个断言被侵犯了! “this”和“p”指的是相同的存储位置。 存储位置发生了变化,所以“this”的内容会发生变化,因为它们是相同的东西。 该结构不能强制x和y的只读性,因为该结构不拥有存储; 存储是一个局部variables,可以随意变异。

你不能依赖一个结构中的只读字段永远不会被改变的不变性; 唯一可以依赖的是你不能直接修改它的代码。 但是有了这样一个鬼鬼祟祟的工作,你可以间接地改变你想要的一切。

另请参阅Joe Duffy关于此问题的出色博客文章:

http://joeduffyblog.com/2010/07/01/when-is-a-readonly-field-not-readonly/

这将使它确实无法改变。 我想你最好添加一个构造函数。
如果它的所有成员都是不变的,那么这将使它完全不可改变。 这些可以是类或简单的值。

编译器将禁止分配readonly字段以及只读属性。

我build议使用只读属性主要是为了公共接口的原因和数据绑定(这不会在字段上工作)。 如果这是我的项目,我会要求,如果结构/类是公共的。 如果它是一个程序集内部的,或者是一个类的私有的,我可以忽略它,稍后将它重构为只读属性。