private NativeArray<State> m_states;
private State[] m;
void Test()
{
ref var state = ref m_states[0]; // this doesn't works.
ref var state1 = ref m[0]; // this works.
ModifyStateAction(ref m[0]); // this works.
ModifyStateAction(ref m_states[0]); // this doesn't works.
}
Exception: Indexer access returns temporary value.‘ref’ argument must be an assignable variable, field or an array element.
Yes, you are right. I have a nested NativeArray in the struct State, that’s why I can’t simply assign a new struct. But I found out I can just modify the NativeArray, so no problem now, thanks for your help!
Because the operator[ ] on NativeArray (same for List etc) is a method that returns ‘T’, not ‘ref T’.
The built-in array T[ ] is somewhat special in that it behaves as if it returned a ‘ref T’ (this behaviour actually predates the introduction of ref returns into the language).
EDIT: To expand on this a bit.
I will use List as an example because NativeArray is a bit more complex, but the reasoning is the same.
List overloads the operator[ ] with something that looks like this:
class List<T> {
T[] _internal_array;
public T this[int idx]{
return _internal_array[idx];
}
// this is equivalent to
// public T this[int idx]{
// var temporary = _internal_array[idx];
// return temporary;
// }
}
What happens when you call myList[5] is:
The fifth element of _internal_array is copied into a temporary storage place (‘onto the stack’)
That temporary is returned.
So now when you try to do var ref x = ref myList[5]; you are creating a reference to what myList[5] returns, which is that temporary storage.
This is never what you actually want and the compiler throws an error when you try.
C#7 introduced a concept of ‘ref return’, allowing you to write something like:
class MyList<T> {
T[] _internal_array;
public ref T this[int idx]{
return ref _internal_array[idx];
}
// equivalent:
// public ref T this[idx]{
// var ref temporary = _internal_array[idx];
// return temporary;
// }
}
Here the method itself returns a ref T, so doing var ref x = ref myList[5]; doesn’t try to create a reference, it just stores the reference that operator[ ] already created for you.
/EDIT
What I would be interested in is: does anyone know the reason NativeArray op[ ] doesn’t retun ‘ref T’?
How would you get it into another context? (you can’t store a ref into persistent storage, both ref variables and ref structs have to live on the stack).