Open
Description
using System.Collections.Generic;
class Program
{
static int[] Test(MyArray x) => [ ..x];
}
struct MyArray
{
public IEnumerator<int> GetEnumerator() => null;
public int Length => 0;
}
Observed:
Compiler copies parameter of Test
into a local and then uses that local for the purpose of populating resulting array.
It feels like the copy is not necessary and the parameter can be used directly.
IL for Test
method:
.method private hidebysig static
int32[] Test (
valuetype MyArray x
) cil managed
{
// Method begins at RVA 0x2050
// Code size 66 (0x42)
.maxstack 3
.locals init (
[0] valuetype MyArray,
[1] int32,
[2] int32[],
[3] class [System.Runtime]System.Collections.Generic.IEnumerator`1<int32>,
[4] int32
)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldc.i4.0
IL_0003: stloc.1
IL_0004: ldloca.s 0
IL_0006: call instance int32 MyArray::get_Length()
IL_000b: newarr [System.Runtime]System.Int32
IL_0010: stloc.2
IL_0011: ldloca.s 0
IL_0013: call instance class [System.Runtime]System.Collections.Generic.IEnumerator`1<int32> MyArray::GetEnumerator()
IL_0018: stloc.3
.try
{
// sequence point: hidden
IL_0019: br.s IL_002c
// loop start (head: IL_002c)
IL_001b: ldloc.3
IL_001c: callvirt instance !0 class [System.Runtime]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
IL_0021: stloc.s 4
IL_0023: ldloc.2
IL_0024: ldloc.1
IL_0025: ldloc.s 4
IL_0027: stelem.i4
IL_0028: ldloc.1
IL_0029: ldc.i4.1
IL_002a: add
IL_002b: stloc.1
IL_002c: ldloc.3
IL_002d: callvirt instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext()
IL_0032: brtrue.s IL_001b
// end loop
IL_0034: leave.s IL_0040
} // end .try
finally
{
// sequence point: hidden
IL_0036: ldloc.3
IL_0037: brfalse.s IL_003f
IL_0039: ldloc.3
IL_003a: callvirt instance void [System.Runtime]System.IDisposable::Dispose()
// sequence point: hidden
IL_003f: endfinally
} // end handler
// sequence point: hidden
IL_0040: ldloc.2
IL_0041: ret
} // end of method Program::Test