在C#中,现在有多种方法来创建临时集合.
你可以新建一个array,希望垃圾收集器不会介意.
// Just create a new array
Span<int> array = new int[]{ 1, 2 };
在unsafe
上下文中,您可以使用stackalloc在堆栈上创建临时回收,从而减少垃圾收集器的负载.
// Create a new array on the stack
Span<int> stack = stackalloc int[2];
stack[0] = 1;
stack[1] = 2;
但现在,在最新的C#版本中,您也可以使用collection expression.
Span<int> span = [1, 2];
我对新集合表达式的工作原理有些困惑.尤其是现在,Visual Studio建议将堆栈分配转换为集合表达式.这意味着它们是等同的?
通常,我不会只是在性能关键部分中新建一个数组,并倾向于使用stackalloc.集合表达式的新语法非常方便.但我真的搞不懂它在引擎盖下是如何运作的.
C#specification建议,当分配给Span时,集合表达式可能会变成堆栈分配.但我不确定这一点目前是否/如何实施.我试着看过SharpLab gist室的IL代表.我真的不太习惯看IL.但是集合表达式和堆栈分配肯定不具有相同的IL表示.这是否意味着它目前不能将集合表达式转换为stackalLocs?
// stackalloc
ldc.i4.8
conv.u
localloc
ldc.i4.2
newobj instance void valuetype [System.Runtime]System.Span`1<int32>::.ctor(void*, int32)
stloc.s 4
ldloc.s 4
stloc.1
ldloca.s 1
ldc.i4.0
call instance !0& valuetype [System.Runtime]System.Span`1<int32>::get_Item(int32)
ldc.i4.1
stind.i4
ldloca.s 1
ldc.i4.1
call instance !0& valuetype [System.Runtime]System.Span`1<int32>::get_Item(int32)
ldc.i4.2
stind.i4
// collection expressions
ldloca.s 3
initobj valuetype '<>y__InlineArray2`1'<int32>
ldloca.s 3
ldc.i4.0
call !!1& '<PrivateImplementationDetails>'::InlineArrayElementRef<valuetype '<>y__InlineArray2`1'<int32>, int32>(!!0&, int32)
ldc.i4.1
stind.i4
ldloca.s 3
ldc.i4.1
call !!1& '<PrivateImplementationDetails>'::InlineArrayElementRef<valuetype '<>y__InlineArray2`1'<int32>, int32>(!!0&, int32)
ldc.i4.2
stind.i4
ldloca.s 3
ldc.i4.2
call valuetype [System.Runtime]System.Span`1<!!1> '<PrivateImplementationDetails>'::InlineArrayAsSpan<valuetype '<>y__InlineArray2`1'<int32>, int32>(!!0&, int32)
stloc.2
有没有人更好地了解新的集合表达式在幕后是如何工作的,以及性能特征是什么,特别是在它生成垃圾的情况下?