The code belows contains a simple LINQ query inside an immutable struct.
struct Point
{
static readonly List*enum*/> NeighborIndexes;
//and ot
Instance methods on structs are called with a reference to this
– a hidden ref parameter.
This is why struct methods are able to mutate the structs they're called on.
When you use this
(or any other local variable / parameter) inside a lambda expression or LINQ query, the compiler turns it into a field on a compiler-generate closure class.
The CLR does not support ref
fields, so it would be impossible for the captured this
to work the same way as a regular this
. (this is also the reason that you can't use ref
parameters inside lambdas)
Iterator methods have the same issue – they are compiled into a hidden enumerator class, and all variables or parameters become fields in the class (this is why iterators cannot take ref
parameters).
However, for iterators, C# made the opposite decision. Inside an iterator, you can use this, but it will be copied to a field on the enumerator class.
This means that if you mutate a struct inside an iterator, the mutations will not happen to the caller's copy.