No, you are not right. The documentation on readonly struct
is perfectly correct. Your question contains a broken link, the correct URL of this documentation page and section is this.
The explanation is pretty simple. Consider this example:
readonly struct A {
internal A(int first, string second) { First = first; Second = second; }
internal readonly int First { get; init; }
internal readonly string Second { get; init; }
}
static class ReadonlyUsage {
static A value = new(0, "original value");
internal static void Demo() {
A a = new(1, "constant value");
//a.First = 12; // will fail to compile
a = new(2, "another value");
// this is mutable:
value = new(3, "one more value");
//value.First = 13; // will fail to compile
// still mutable:
value = new(4, "How much longer?!");
}
}
What is mutable here? Nothing except ReadonlyUsage.value
, and it makes ReadonlyUsage
also mutable. It has nothing to do with struct A
— it is immutable. Exactly as System.String
.
Let's see: what about the assignment to A a
? Does this assignment make ReadonlyUsage
mutable? No. You assign a new value (and struct A
is a value type) to a stack variable. It exists only in the stack and will be removed after the exit of a current stack frame. The stack does not belong to the class, it belongs to the thread calling ReadonlyUsage.Demo
. The assignment does not modify anything in the Demo
class if it was an instance class. We simply create a new struct A
instance and never modify any of the already existing instances, that's why it is called immutable.
Now, what about the assignment to ReadonlyUsage.value
? It is possible, because ReadonlyUsage
is mutable. Again, we create new instances of struct A
and never modify any of the already existing instances.
How to prevent the assignment to ReadonlyUsage.value
? Easy: make it readonly
, too:
static readonly A value = new(0, "original value");
That's it. I hope the misunderstanding is dismissed. Will you accept the answer then? If not, please ask further questions.