Why are mutable structs “evil”?
Structs are value types which means they are copied when they are passed around.
So if you change a copy you are changing only that copy, not the original and not any other copies which might be around.
If your struct is immutable then all automatic copies resulting from being passed by value will be the same.
If you want to change it you have to consciously do it by creating a new instance of the struct with the modified data. (not a copy)
Where to start ;-p
Eric Lippert's blog is always good for a quote:
This is yet another reason why mutable value types are evil. Try to always make value types immutable.
First, you tend to lose changes quite easily... for example, getting things out of a list:
Foo foo = list[0];
foo.Name = "abc";
what did that change? Nothing useful...
The same with properties:
myObj.SomeProperty.Size = 22; // the compiler spots this one
forcing you to do:
Bar bar = myObj.SomeProperty;
bar.Size = 22;
myObj.SomeProperty = bar;
less critically, there is a size issue; mutable objects tend to have multiple properties; yet if you have a struct with two int
s, a string
, a DateTime
and a bool
, you can very quickly burn through a lot of memory. With a class, multiple callers can share a reference to the same instance (references are small).
I wouldn't say evil but mutability is often a sign of overeagerness on the part of the programmer to provide a maximum of functionality. In reality, this is often not needed and that, in turn, makes the interface smaller, easier to use and harder to use wrong (= more robust).
One example of this is read/write and write/write conflicts in race conditions. These simply can't occur in immutable structures, since a write is not a valid operation.
Also, I claim that mutability is almost never actually needed, the programmer just thinks that it might be in the future. For example, it simply doesn't make sense to change a date. Rather, create a new date based off the old one. This is a cheap operation, so performance is not a consideration.
Mutable structs are not evil.
They are absolutely necessary in high performance circumstances. For example when cache lines and or garbage collection become a bottleneck.
I would not call the use of a immutable struct in these perfectly valid use-cases "evil".
I can see the point that C#'s syntax does not help to distinguish the access of a member of a value type or of a reference type, so I am all for preferring immutable structs, that enforce immutability, over mutable structs.
However, instead of simply labelling immutable structs as "evil", I would advise to embrace the language and advocate more helpful and constructive rule of thumbs.
For example: "structs are value types, which are copied by default. you need a reference if you don't want to copy them" or "try to work with readonly structs first".