Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReadonlySpan As Property

Tags:

c#

.net-core

I try to understand .net core 3.0. As far as i know, i cannot use Span or ReadonlySpan as properties or members since it is stack based struct. And I want to know the differences between the following definition. I can successfully define 'part1' without any error. I received the following compile error for part2 "A result of a stackalloc expression of type Span cannot be used in this context" For part3, i received the different compile error. "Field or auto-implemented property cannot be type ReadonlySpan"

public class KeyGenWithSpan
{
   private static ReadOnlySpan<char> part1 => new[] { 'p', '1'};
   private static ReadOnlySpan<char> part2 => stackalloc[]{'1','2'};
   private static ReadOnlySpan<char> part3 = stackalloc[]{'1','2'};
}
like image 516
arnold park Avatar asked Jul 16 '26 02:07

arnold park


1 Answers

The span is a stack-based struct, but the data can be anywhere. It could be in an array, it could be unmanaged memory, it could be the stack, it could be a "fixed buffer", or a string, etc.

You can have spans as properties. What you can't have is spans as fields, except on ref struct types. The property would act as a proxy to get the span from something (perhaps an array).

In part1, you're allocating a new array every time, but that isn't necessary - it can be done smarter.

This however, is not possible for stackalloc, since stackalloc would allocate in the property getter's stack-frame, which no longer exists when you exit the getter.

Consider:

private static readonly char[] s_data = { 'p', '1'};
public static ReadOnlySpan<char> Data => s_data; // perfectly valid conversion

Note that for some types (notably: not char), the compiler can do extra voodoo here:

public static ReadOnlySpan<byte> Data2 => new byte[] { 0, 1 };

does not compile to a new array each time in the getter; instead, it draws directly from the assembly metadata:

.method public hidebysig specialname static valuetype [System.Runtime]System.ReadOnlySpan`1<uint8> get_Data2() cil managed
{
    .maxstack 8
    L_0000: ldsflda int16 <PrivateImplementationDetails>::3F29546453678B855931C174A97D6C0894B8F546
    L_0005: ldc.i4.2 
    L_0006: newobj instance void [System.Runtime]System.ReadOnlySpan`1<uint8>::.ctor(void*, int32)
    L_000b: ret 
}
like image 152
Marc Gravell Avatar answered Jul 17 '26 15:07

Marc Gravell