C# Collection Expressions

C Sharp Programming Tutorials


C# collection expressions provide a concise syntax for creating common collection values with square brackets. Introduced in C# 12, they can initialize arrays, lists, spans, and other supported collection types without repeating constructor or type syntax.

Collection expressions also support the spread element, written with two dots, so values from an existing collection can be inserted into a new collection.

Collection Expression Syntax

// The target type tells the compiler what collection to create.
int[] numbers = [10, 20, 30];
List<string> names = ["Asha", "Mia", "Noah"];

A collection expression does not have a standalone natural type. The compiler uses the surrounding target type to decide what collection should be created.

Because a collection expression needs target typing, code such as var numbers = [1, 2, 3]; is not valid. Specify a compatible target type instead.

Create Arrays and Lists

The following example creates an array, copies its elements into another array with a spread element, and initializes a List directly.

Example:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        int[] first = [72, 88];
        int[] all = [.. first, 95, 91];

        List<string> steps = ["Design", "Build", "Test"];

        Console.WriteLine(string.Join(", ", all));
        Console.WriteLine(string.Join(" -> ", steps));
    }
}

Output:

72, 88, 95, 91
Design -> Build -> Test

Use the Spread Element

A spread element starts with .. followed by an expression that can be enumerated. Its values are inserted into the surrounding collection expression.

Example:

int[] morning = [8, 9];
int[] afternoon = [13, 14];

// Combine existing values with new values.
int[] schedule = [7, .. morning, 12, .. afternoon, 17];

Console.WriteLine(string.Join(", ", schedule));

Output:

7, 8, 9, 12, 13, 14, 17

The spread element is different from the range operator even though both use two dots. Inside a collection expression, ..source means insert the source elements into the new collection.

Create Empty Collections

An empty collection expression is simply []. The target type still determines what object is produced.

string[] tags = [];
List<int> scores = [];

Use Collection Expressions with Spans

Collection expressions can target Span<T> and ReadOnlySpan<T> as well as arrays and List<T>.

ReadOnlySpan<char> vowels = ['a', 'e', 'i', 'o', 'u'];

foreach (char letter in vowels)
{
    Console.Write(letter + " ");
}

Target Typing

The same collection expression can produce different supported collection shapes depending on the target context.

Target Example
Array int[] values = [1, 2, 3];
List List<int> values = [1, 2, 3];
Span Span<int> values = [1, 2, 3];
ReadOnlySpan ReadOnlySpan<int> values = [1, 2, 3];

Target typing also works in method arguments when the parameter type provides the required context.

Example:

static void PrintNames(List<string> names)
{
    Console.WriteLine(string.Join(", ", names));
}

// The parameter type supplies the target type.
PrintNames(["Riya", "Oliver", "Mia"]);

Nested Collection Expressions

You can use collection expressions inside another expression when the element type is itself a supported collection type.

int[][] grid = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

This form is useful for jagged arrays and other nested data structures where the target type makes each inner collection clear.

Common Mistakes

  • Using var without a target type: collection expressions need enough context to determine the resulting collection type.
  • Confusing spread with ranges: ..source inserts elements; it does not select a numeric or index range.
  • Assuming every custom collection works automatically: a type must match one of the supported collection construction patterns.
  • Spreading null: the spread source must be a valid enumerable value at runtime.

When to Use Collection Expressions

  • Initialize short arrays and lists with less repeated syntax.
  • Combine existing sequences with additional values using spread elements.
  • Create empty collections where the target type is already obvious.
  • Pass small collection values directly to methods with compatible parameter types.

Best Practices

  • Keep the target type visible when it improves readability.
  • Use spread elements for clear composition rather than manually copying items.
  • Avoid very large inline expressions when named intermediate collections would be easier to understand.
  • Choose the target collection type according to behavior and performance needs, not only the shortest syntax.

Conclusion

C# collection expressions make common collection creation shorter and more consistent. Use square brackets with an explicit or contextual target type, add spread elements when you need to combine sequences, and keep the resulting collection type clear to readers. The feature reduces initialization boilerplate while preserving normal array, list, and span behavior.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram