This is because of the underlying IL instructions.
The program executes this sequence of instructions to get the desired item:
Load the address onto the stack.
Load the offset on the stack.
Add them.
Read the value at this memory address.
If the object is on the heap and then moves due to garbage collection until step 4, then the address downloaded from step 1 will no longer be valid. To protect against this, you need to first bind the object to memory.
(The fact that you are accessing the structure using the this pointer means that you do not know if the structure is on the heap or on the stack, so you need to attach it just in case it is on the heap.)
The second example works because it copies the structure onto the stack, so the copy can never move, so the address will always be valid.
Why does this problem not occur with other kinds of fields? Since their offset is known at compile time, while the index of the array is known at run time, so JIT can generate code that will always refer to fields correctly.
Mehrdad
source share