dotnet / dotnet/roslyn

Use `ReadOnlySpan<T>.CopyTo` for collection expression

Open
#75,664 5 comments 0 reactions 0 assignees View on GitHub
Area-Compilers Code Gen Quality Feature - Collection Expressions
Dominant language
C#
Stars
20.7k
Forks
4.3k
PR merge metrics
PR metrics pending

Description

### Version Used

Compiler: 4.13.0-1.24518.1 (a98e8c04)
.NET: 9.0.100-rc.2.24474.11
Visual Studio Code: 1.94.2, `384ff7382de624fb94dbaf6da11977bba1ecd427`, x64
C# Extension: v2.53.17
C# Dev Kit Extension: v1.12.27

### Background and Motivation

Today, collection expressions add each item individually.
According to [sharplab.io](https://sharplab.io/#v2:EYLgtghglgdgPgAQAwAIEEYAsBuAsAKAIBkoBnAFwB5ZyA+FAMwHsmUBeFAbXQBoUAmPgGYAutiA), the below source code is compiled as such:
```cs
List foo = [1, 2, 3];
```
```cs
int num = 3;
List list = new List(num);
CollectionsMarshal.SetCount(list, num);
Span span = CollectionsMarshal.AsSpan(list);
int num2 = 0;
span[num2] = 1;
num2++;
span[num2] = 2;
num2++;
span[num2] = 3;
num2++;
```

At small sizes, this should be fine. When a developer adds a lot of items, however, this implementation seems less appropriate and less performant than generating a `ReadOnlySpan` that can be copied to the `List` via `CopyTo`.

### Proposed Feature

Roslyn generates a member like the following:
```cs
static ReadOnlySpan _compilerGeneratedMember => new int[3] { 1, 2, 3 };
```
And instead compiles to the below code:
```cs
Span span = CollectionsMarshal.AsSpan(list);
_compilerGeneratedMember.CopyTo(span);
```

### Additional Notes

The feature may not work well with reference types?
The feature can make use of some "threshold", where the `ReadOnlySpan.CopyTo` approach is only used when a significant amount of individual items in a row are present in the collection expression.
The feature can be expanded to anywhere a collection expression takes some amount of individual items in a row, such as in this example:
```cs
List M(List source) => [.. source, 1, 2, 3];
```

Contributor guide

Open the contributing guide

Research direction

Start by tracing Roslyn's collection-expression lowering and how it currently emits individual element assignments for List. Compare a ReadOnlySpan.CopyTo approach for large runs of elements, then validate semantics and generated code for value types, reference types, thresholds, and the spread example described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.