Given the method
ref readonly State GetState();
where State
is a struct
, the following code accesses State.SimTime
without copying State
:
ref readonly var state = ref GetState();
var t = state.SimTime;
Meanwhile this code does copy State
:
var start = GetState();
var t = state.SimTime;
My question is whether the following copies State
:
var t = GetState().SimTime;
My hope is that it doesn't, since the result of GetState()
is a ref and never assigned, but I don't know for sure and don't know how I would test for it.
As a bonus, is there a way to inspect code staticcally to determine whether memory is copied?
GetState().SimTime
does not create a copy of State
. You can see this by looking at the generated IL on SharpLab or some other tool.
GetState().SimTime
gets compiled to two call
instructions:
// IL pseudocode
call GetState
call get_SimTime
The code snippet that uses a ref readonly var
compiles to the same two call
instructions.
On the other hand, the code snippet that does not use ref readonly var
compiles to:
// IL pseudocode
call GetState
ldobj State
stloc.0
ldloca.s 0
call get_SimTime
The key instruction here is ldobj
- this is what turns the reference that GetState
returns, into an actual struct value (i.e. the copy of State
). If you don't see an instruction like ldobj
after calling a ref-return method, that means the code is operating on the reference returned by the method, and not a struct value.
As Marc Gravell's answer says, the runtime would create a defensive copy if the getter of SimTime
has side effects.