Skip to content

Inefficient lowering of spreading collection expression targeting IEnumerable<> #79243

Closed as not planned
@petrroll

Description

@petrroll

When using collection expression targeted to IEnumerable<T> to append a single item into something that also implements IEnumerable<T>, I'd expect it being lowered into something at least as efficient as source.Concat([newObj]);

Instead it is lowered as creating new array, copying data into it, and wrapping that into compiler generated Readonlyarray.

using System.Collections.Generic;
public class C {
    public void M(IReadOnlyList<object> source) {
        IEnumerable<object> extendedState = [.. source, new()];
    }
}

->

public class C
{
    [NullableContext(1)]
    public void M(IReadOnlyList<object> source)
    {
        int num = 0;
        object[] array = new object[1 + source.Count];
        IEnumerator<object> enumerator = source.GetEnumerator();
        try
        {
            while (enumerator.MoveNext())
            {
                object obj = (array[num] = enumerator.Current);
                num++;
            }
        }
        finally
        {
            if (enumerator != null)
            {
                enumerator.Dispose();
            }
        }
        array[num] = new object();
        num++;
        new <>z__ReadOnlyArray<object>(array);
    }
}

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABADAAgwRhQG4BYAKAwGY8AmHAYRwG9yc29qMUcBZACgCSAJRgBDACYB5AHYAbAJ4AZAJYBnAC4AeCMABWMMOoB8OVRACuUMDACUzVu0cFK2vQeM4YCdTGniY4gDK6qI+OAC8OADaAHQxphZWMAA0ONIwAO58NgC6pGSOAL7khUA==

This seems rather unexpected. While allocations are unavoidable in this case, copying the whole - potentially super big enumerable - into an array seems avoidable.

It generally seems that collectoin expressions tagetting IEnumerable-like things prefer everything being backed by already realized memory instead of constructing LINQ.

As evident by changing type of the source: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABADAAgwRhQG4BYAKAwGY8AmHAYRwG9yc29qMUcBZACgKUAPBGAArGGAAuAPhwBnCAFcoYGAEpmrdjsEjxk2ThgIpMAHYATGJYDKUgIZmcAXhwBtAHSeFy1TAAaHHMYAHc+dQBdUjIdAF9yOKA

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions