我尝试了解.net core 3.0。 据我所知,我不能使用Span或ReadonlySpan作为属性或成员,因为它是基于堆栈的结构。 我想知道以下定义之间的区别。 我可以成功定义'part1',而不会出现任何错误。 我收到了第2部分的以下编译错误 “在这种情况下,不能使用Span类型的stackalloc表达式的结果” 对于第3部分,我收到了不同的编译错误。 “字段或自动实现的属性不能为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'};
}
答案 0 :(得分:3)
span 是基于堆栈的结构,但是 data 可以是任意位置。它可以在数组中,可以是非托管内存,可以是堆栈,可以是“固定缓冲区”或字符串等。
您可以将跨度作为属性。除了<ref struct
类型之外,您无法拥有的范围是 fields 。该属性将充当 proxy 的作用,以从某个对象(可能是数组)获取跨度。
在part1
中,您每次都分配一个新数组,但这不是必需的-它可以更智能地完成。
但这对stackalloc
来说是不可能的,因为stackalloc
会在属性getter的堆栈框架中分配 ,当您退出getter时,该框架不再存在。 / p>
考虑:
private static readonly char[] s_data = { 'p', '1'};
public static ReadOnlySpan<char> Data => s_data; // perfectly valid conversion
请注意,对于某些类型(值得注意的是:不是char
),编译器可以在此处进行额外的巫术:
public static ReadOnlySpan<byte> Data2 => new byte[] { 0, 1 };
每次在getter中不会编译为新数组;相反,它直接从程序集元数据中提取:
.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
}