[英]Does C# Collection Initialization Syntax Avoid Default Initialization Overhead
When you use the new C# collection initialization syntax: 使用新的C#集合初始化语法时:
string[] sarray = new[] { "A", "B", "C", "D" };
does the compiler avoid initializing each array slot to the default value, or is it equivalent to: 编译器是否避免将每个数组槽初始化为默认值,或者它是否等效于:
string[] sarray = new string[4]; // all slots initialized to null
sarray[0] = "A";
sarray[1] = "B";
sarray[2] = "C";
sarray[3] = "D";
The compiler still uses the newarr
IL instruction, so the CLR will still initialize the array. 编译器仍然使用
newarr
IL指令,因此CLR仍将初始化数组。
Collection initialization is just compiler magic - the CLR doesn't know anything about it, so it'll still assume it has to do sanity clearance. 集合初始化只是编译器的魔力 - CLR对它一无所知,所以它仍然认为它必须做清理。
However, this should be really, really quick - it's just wiping memory. 但是,这应该非常非常快 - 它只是擦拭内存。 I doubt it's a significant overhead in many situations.
我怀疑在许多情况下这是一个重大的开销。
Quick test: 快速测试:
string[] arr1 =
{
"A","B","C","D"
};
arr1.GetHashCode();
string[] arr2 = new string[4];
arr2[0] = "A";
arr2[1] = "B";
arr2[2] = "C";
arr2[3] = "D";
arr2.GetHashCode();
results in this IL (note, they're both identical) 结果在这个IL(注意,它们都是相同的)
IL_0002: newarr [mscorlib]System.String
IL_0007: stloc.2
IL_0008: ldloc.2
IL_0009: ldc.i4.0
IL_000a: ldstr "A"
IL_000f: stelem.ref
IL_0010: ldloc.2
IL_0011: ldc.i4.1
IL_0012: ldstr "B"
IL_0017: stelem.ref
IL_0018: ldloc.2
IL_0019: ldc.i4.2
IL_001a: ldstr "C"
IL_001f: stelem.ref
IL_0020: ldloc.2
IL_0021: ldc.i4.3
IL_0022: ldstr "D"
IL_0027: stelem.ref
IL_0028: ldloc.2
IL_0029: stloc.0
IL_002a: ldloc.0
IL_002b: callvirt instance int32 [mscorlib]System.Object::GetHashCode()
IL_0030: pop
IL_0031: ldc.i4.4
IL_0032: newarr [mscorlib]System.String
IL_0037: stloc.1
IL_0038: ldloc.1
IL_0039: ldc.i4.0
IL_003a: ldstr "A"
IL_003f: stelem.ref
IL_0040: ldloc.1
IL_0041: ldc.i4.1
IL_0042: ldstr "B"
IL_0047: stelem.ref
IL_0048: ldloc.1
IL_0049: ldc.i4.2
IL_004a: ldstr "C"
IL_004f: stelem.ref
IL_0050: ldloc.1
IL_0051: ldc.i4.3
IL_0052: ldstr "D"
IL_0057: stelem.ref
IL_0058: ldloc.1
IL_0059: callvirt instance int32 [mscorlib]System.Object::GetHashCode()
I ran a short test on instantianting an array using the syntax you describe and found that instantiating with non-default values took about 2.2 fold longer than instantiantion with default values. 我使用您描述的语法对实例化数组进行了一个简短的测试,发现使用非默认值实例化的时间比使用默认值的实例长约2.2倍。
When I switched and instantiated with default values, it takes about the same amount of time. 当我使用默认值切换和实例化时,它需要大约相同的时间。
Indeed, when I looked at the decompile it appears that what happens is the array is initialized, and then is populated with any values that are not the default. 实际上,当我查看反编译时,似乎发生了什么是数组被初始化,然后填充了任何非默认值。
Instantiating with non default values: 使用非默认值进行实例化:
bool[] abPrimes = new[] {
true, true
};
0000007e mov edx,2
00000083 mov ecx,79114A46h
00000088 call FD3006F0
0000008d mov dword ptr [ebp-64h],eax
00000090 mov eax,dword ptr [ebp-64h]
00000093 mov dword ptr [ebp-54h],eax
00000096 mov eax,dword ptr [ebp-54h]
00000099 cmp dword ptr [eax+4],0
0000009d ja 000000A4
0000009f call 76A9A8DC
000000a4 mov byte ptr [eax+8],1
000000a8 mov eax,dword ptr [ebp-54h]
000000ab cmp dword ptr [eax+4],1
000000af ja 000000B6
000000b1 call 76A9A8DC
000000b6 mov byte ptr [eax+9],1
000000ba mov eax,dword ptr [ebp-54h]
000000bd mov dword ptr [ebp-40h],eax
Instantiating with default values: 使用默认值进行实例化:
bool[] abPrimes2 = new[] {
false, false
};
000000c0 mov edx,2
000000c5 mov ecx,79114A46h
000000ca call FD3006F0
000000cf mov dword ptr [ebp-68h],eax
000000d2 mov eax,dword ptr [ebp-68h]
000000d5 mov dword ptr [ebp-54h],eax
000000d8 mov eax,dword ptr [ebp-54h]
000000db mov dword ptr [ebp-5Ch],eax
It is not possible to avoid initializing each array slot to the default value, at least in IL level. 不可能避免将每个阵列槽初始化为默认值,至少在IL级别。
String is a CLASS, not a struct. String是CLASS,而不是struct。
That means A, B, C, D and the sarray could be stored in any position. 这意味着A,B,C,D和sarray可以存储在任何位置。 A, B, C and D might be get from the Intern pool, that the reference to the object could be dynamic.
A,B,C和D可能来自Intern池,对象的引用可能是动态的。
But I believe that the JIT could smart enough to reduce half of these overhead. 但我相信JIT可以足够聪明地减少一半的开销。
PS. PS。 Premature optimization being the root of all evil.
过早优化是万恶之源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.