在.Net 8中集合初始化的新语法
前言
在.Net 8中C#的版本也升级到了12.在集合初始化这一块也带来新的语法,在集合初始化的时候,更方便了.目前来看这是一个语法糖.这个集合初始化的语法,主要在
- 数组
- Span<T>和ReadOnlySpan<T>
- List<T>
代码示例
// 数组
// //使用[]代替new in[],不用写具体示例化类型
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];
// Span
Span<int> b = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];
// 创建二维数组
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
为了确定这个新语法,是否为是语法糖,用IlSpy反编译生成后的代码,发现IlSpy目前还不支持C# 12的语法,用C# 11和IL反编译生成后的代码:
性能测试和汇编代码分析
using BenchmarkDotNet.Attributes;
namespace CSharpBenchmarks.ArrayTest
{
[MemoryDiagnoser]
[DisassemblyDiagnoser(printSource: true)]
public class NewSyntaxTest
{
[Params(10000)]
public int Times { get; set; }
[Benchmark]
public void ArrayTest1()
{
for (int i = 0; i < Times; i++)
{
int[] arr = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
if (arr.Length > 0)
{
}
}
}
[Benchmark]
public void ArrayTest2()
{
for (int i = 0; i < Times; i++)
{
int[] arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
if (arr.Length > 0)
{
}
}
}
}
}
性能测试结果:
发现性能测试在耗时上有微小的差异,在生成汇编代码和GC及内存分配上,都是一样的,在对比生成汇编代码后,可以确定这个语法就是语法糖,只是简化集合初始化而已.下面我们来看看汇编代码:
; CSharpBenchmarks.ArrayTest.NewSyntaxTest.ArrayTest2()
; for (int i = 0; i < Times; i++)
; ^^^^^^^^^
; int[] arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; if (arr.Length > 0)
; ^^^^^^^^^^^^^^^^^^^
push rdi
push rsi
push rbx
sub rsp,20
vzeroupper
mov rbx,rcx
xor esi,esi
cmp dword ptr [rbx+8],0
jle short M00_L01
mov rdi,offset MT_System.Int32[]
M00_L00:
mov rcx,rdi
mov edx,0A
call CORINFO_HELP_NEWARR_1_VC ;;创建数组
mov rcx,1E73D3286D0
vmovdqu ymm0,ymmword ptr [rcx]
vmovdqu ymmword ptr [rax+10],ymm0
mov rdx,[rcx+20]
mov [rax+30],rdx
inc esi
cmp esi,[rbx+8]
jl short M00_L00
M00_L01:
add rsp,20
pop rbx
pop rsi
pop rdi
ret
; Total bytes of code 86
只看新语法生成的汇编代码,其实和new int[]是一样的.
在.Net 8中BCL库和Asp.Net Core中已经开始使用新语法,可以看一下这个Issue #93126
秋风
2023-10-09