Surprising codegen for passing collection spread to span/readonlyspan taking method. #76488
Closed as duplicate of#75863
Closed as duplicate of#75863
Description
Consider this code:
using System;
using System.Collections.Generic;
class C
{
void Main(IEnumerable<string> values)
{
Goo([.. values, .. values]);
}
void Goo(ReadOnlySpan<string> spans)
{
}
}
We generate the equivalent of:
List<string> list = new List<string>();
list.AddRange(values);
list.AddRange(values);
Goo(new ReadOnlySpan<string>(list.ToArray()));
The copy to an array seems unnecessary here, and more ideal codegen would seem to be:
List<string> list = new List<string>();
list.AddRange(values);
list.AddRange(values);
Goo(System.Runtime.InteropServices.CollectionsMarshal.AsSpan(list));
This would prevent a needless copy. Note that this should be entirely safe as:
- The backing list is an impl detail hidden from the user (they cannot mutate it).
- writing back into the list through the span would continue to be supported, but would also continue to be pointless.
This seems like a safe, and desirable change to make (as long as CollectionsMarshal.AsSpan is available) whenever we are targetting a span/read-only-span with a variable length number of elements.