Ok, let's have some code:
//I complie nicely
ValueType[] good = new ValueType[1];
good[0].Name = "Robin";
//I don't compile: Cannot modify expression because its not a variable
IList<ValueType> bad = new ValueType[1];
bad[0].Name = "Jerome";
struct ValueType
{
public string Name;
}
What precisely is going on behind the scenes that is causing the compiler to baulk?
//Adding to watch the following
good.GetType().Name //Value = "ValueType[]" It's a ValueType array.
bad.GetType().Name //Value = "ValueType[]" Also a ValueType array.
The compiler is stopping me from modifying a member of the copy of the object I want to change. But why is a copy being made from this array?
A little more research throws up:
var guess = (ValueType[]) bad;
guess[0].Name="Delilah";
Now, what do you think bad[0].Name
is? That's right, it's "Delilah".
type and immutable are valid up to julia 0.6, mutable struct and struct are the names of the same objects in julia 0.6 and forward. mutable in mutable struct means that the fields can change - which is actually fairly rarely used so being immutable is the default. mutable struct 's are slower than struct s.
Yep, you're right, structs are not immutable. The thing about structs is that they are values. That means every variable is considered a copy, and its members are isolated from changes made to other variables. Structs are not copied on mutation.
Reasons to make structs immutableStructs are copied by value, not by reference. It is easy to accidentally treat a struct as being copied by reference.
The generated properties in record structs are mutable by default. The reason behind this decision was to be consistent with tuples. Tuples are like anonymous record structs with similar features. On the other hand, struct mutability does not carry the same level of concern as class mutability does.
Why is a value type being copy-returned from the
IList<ValueType>
but not from the array
Because an array is a built-in construct known to the compiler. Its operator []
has a built-in semantic, which provides the compiler with a modifiable reference inside the array itself.
When the compiler deals with an interface, on the other hand, all it knows it that it gets back a copy of a value type, which you are trying to modify. In other words, the compiler views IList
's operator []
and array's operator []
differently.
Note: it goes without saying that this exercise is of purely academic value, because mutable structs are evil.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With