If you intend to use structures, it is best to make them immutable.
Creating all readonly fields is a great way to help (1) document that the structure is immutable and (2) prevent accidental mutations.
However, there is one wrinkle that, in a strange coincidence, I was planning to blog about next week. That is: readonly in the struct field is false . You can expect that the readonly field cannot change, but of course it is possible. "readonly" in the struct field is a declaration that writes checks without money in your account. The structure does not have its own repository, and it is a repository that can mutate.
For example, take your structure:
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;
Is there anything that can happen when “something happens here” that breaks debug statements? Sure.
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);
Now what is happening? Approval violated! "this" and "p" refer to the same storage location. The storage location is mutated, so the contents of "this" are mutated because it is one and the same. The structure cannot provide read-only x and y because the structure does not own the repository; storage is a local variable that can mutate as much as it wants.
You cannot rely on an invariant that is never observed for a readonly field in a structure; the only thing you can rely on is that you cannot write code that directly changes it. But, by stealing this work a little, you can indirectly change everything you want.
See also Joe Duffy's excellent blog article on this issue:
http://joeduffyblog.com/2010/07/01/when-is-a-readonly-field-not-readonly/
Eric Lippert May 19 '11 at 18:56 2011-05-19 18:56
source share