I'm playing with stackalloc
and finding al lot of weirdness in its return type. Here are some examples using stackalloc<float>
:
1. Implicit typing returns float*
:
var a = stackalloc float[1];//a is float*
2. Declaring a float*
and setting it using stackalloc
doesn't compile:
float* a;
a = stackalloc float[1];//CS8346 conversion of a stackallock expression of type 'float' to type 'float*' is not possible
3. Declaring the float*
inline works just fine:
float* a = stackalloc float[1];
4. A similar behavior happens for Span<float>
This works just fine:
Span<float> a = stackalloc float[1];
But this doesn't compile:
Span<float> a;
a = stackalloc float[1];//CS8353 A result of a stackalloc expression of type 'Span<float>' cannot be used in this context because it may be exposed outside of the containing method
5. What makes this whole situation even weirder is that there is no implicit conversion between Span<float>
and float*
or vise versa.
So what exactly is stackalloc float[1]
returning? And why is the above behavior ocurring?
This code was written using VS 2019 C# version 9.0, .NET 5.
CodePudding user response:
As per C# 6 draft specification stackalloc
:
In an unsafe context, a local variable declaration (Local variable declarations) may include a stack allocation initializer which allocates memory from the call stack.
i.e. it can be used only in declarations which you have called "inline".
As per language reference stackalloc
does not have single defined return type but "allocates a block of memory on the stack" and then:
You can assign the result of a stackalloc expression to a variable of one of the following types:
- Beginning with C# 7.2,
System.Span<T>
orSystem.ReadOnlySpan<T>
- A pointer type
Some interesting extra links:
- C# - All About Span: Exploring a New .NET Mainstay by Stephen Toub.
- CS8353 dicussion on github
- Why does a zero-length stackalloc make the C# compiler happy to allow conditional stackallocs?