❔ Benefit of ref structs
Hey folks!
I've been trying for a bit to understand the purpose of using a ref struct over a regular struct. I understand that it can only live on the stack, which is enforced via a set of usage rules, but regular structs could do that too if used properly.
I asked my good old friend chatgpt to help me understand it, and the answer I got was basically that the compiler is able to optimize the usage of ref structs better given its restrictions. Is this accurate? Is it the only benefit?
I'm used to concepts like the
out
keyword where its usage restrictions (must be populated by return, cannot be read) come as a tradeoff for visible benefits (inline variable declaration in a method call), so I guess I was expecting something similar in this case, specifically something that can only be done with ref structs.26 Replies
the truth is that ref structs exist because of
Span<T>
they had to invent a new language mechanic to make Span<T>
a thing, and that was ref struct
Why did
Span<T>
need the restrictions?one of the big use-cases of
Span<T>
was to be able to provide windows into arrays
and in particular
stackalloc'd arraysCould that not have worked without the concept of ref structs?
not really
what you can do with the advent of ref struct and Span<T> is
numbers
here becomes a Span<T>
or to REALLY highlight where the optimization potential is....
even if you KNOW this allocation is small, and you're only going to need it for a short while
before Span<T>
and stackalloc
this would HAVE to be allocated on the heap
and put pressure on the GCI'll have to take some time to digest that later
if you have a big hot path that does something like this, the best you could do before was implement some kind of array pooling
I.E. allocate one array/List<T> ahead of time (or several), and reuse it
stackalloc
lets you swap out a complex heap allocation, which also creates comples GC work for later, with the equivalent of...
Could Memory<T> not have worked in its place?
var memory = stackalloc...
it's the equivalent of declaring
length
number of int
local method variables, and then Span<T>
just gives you an API over that
nope, Memory<T>
is not a ref struct
and therefore
it can get captured and boxed onto the heapSure but pretending ref struct was never invented
Could stackalloc not have worked with memory?
Why does ref struct allow stackalloc?
not really
b/c ref structs cannot be heaped
Span<T>
does work very similarly to Memory<T>
it's in part b/c the GC doesn't like dealing with ref fields (which ref structs can contain)
it's essentially got a reference to the memory inside itself
but when you copy a
Memory<T>
you're not actually copying the memory it refers to
even though Memory<T>
itself is passed by value, it's value consists of a reference
so, if Memory<T>
were to refer to a stackalloc'd chunk of memory
what could happen is that the Memory<T>
gets captured and put on the heap
that DOES NOT cause the stackalloc'd memory to be copied to the heapalso this kind of question is better suited to #advanced or even #allow-unsafe-blocks than #help
so, now, the method that allocated the memory can finish, thus de-allocating it
but the heap still has that
Memory<T>
which now refers to garbage memoryYeah I'm not understanding it yet, but I'll circle back to digest it later
Thanks folks!
mm-kay
split attention right now unfortunately
Okay it clicked
Thanks again!
the key thing is that a
ref
struct can have a ref
field
X
is a field that is a reference to an int
somewhere in memory. a pointer, if you will
this is only allowed in ref struct
s. Span<T>
, for example, is internally implemented as: (this is copied directly from the source)right that makes sense
If you really want to understand the power of ref structs, go play with rust for a while
ref structs are basically the C# compiler implementing a borrow checker
a borrow-checker that only supports borrowing on the stack, essentially?
Essentially
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.