Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .openpublishing.redirection.csharp.json
Original file line number Diff line number Diff line change
Expand Up @@ -5014,7 +5014,7 @@
},
{
"source_path_from_root": "/docs/csharp/whats-new.md",
"redirect_url": "/dotnet/csharp/whats-new/csharp-14",
"redirect_url": "/dotnet/csharp/whats-new/csharp-15",
"redirect_document_id": true
},
{
Expand Down Expand Up @@ -5055,7 +5055,7 @@
},
{
"source_path_from_root": "/docs/csharp/whats-new/index.md",
"redirect_url": "/dotnet/csharp/whats-new/csharp-14",
"redirect_url": "/dotnet/csharp/whats-new/csharp-15",
"ms.custom": "updateeachrelease"
},
{
Expand Down
10 changes: 8 additions & 2 deletions docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"Compiler Breaking Changes - DotNet 8.md",
"Compiler Breaking Changes - DotNet 9.md",
"Compiler Breaking Changes - DotNet 10.md",
"Compiler Breaking Changes - DotNet 11.md",
"Deviations from Standard.md"
],
"src": "_roslyn/docs/compilers/CSharp",
Expand Down Expand Up @@ -513,11 +514,12 @@
"_csharplang/proposals/csharp-12.0/*.md": "08/15/2023",
"_csharplang/proposals/csharp-13.0/*.md": "10/31/2024",
"_csharplang/proposals/csharp-14.0/*.md": "08/06/2025",
"_csharplang/proposals/*.md": "08/06/2025",
"_csharplang/proposals/*.md": "02/04/2025",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md": "11/08/2022",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md": "11/08/2023",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 9.md": "11/09/2024",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md": "01/09/2024",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md": "11/09/2024",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 11.md": "01/09/2025",
"_roslyn/docs/compilers/CSharp/Deviations from Standard.md": "04/24/2025",
"_vblang/spec/*.md": "07/21/2017"
},
Expand Down Expand Up @@ -693,10 +695,12 @@
"_csharplang/proposals/csharp-14.0/ignored-directives.md": "Ignored preprocessor directives",
"_csharplang/proposals/csharp-14.0/extension-operators.md": "Extension operators",
"_csharplang/proposals/csharp-14.0/optional-and-named-parameters-in-expression-trees.md": "Optional and named parameters in expression trees",
"_csharplang/proposals/collection-expression-arguments.md": "Collection expression arguments",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md": "C# compiler breaking changes since C# 10",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md": "C# compiler breaking changes since C# 11",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 9.md": "C# compiler breaking changes since C# 12",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md": "C# compiler breaking changes since C# 13",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 11.md": "C# compiler breaking changes since C# 14",
"_roslyn/docs/compilers/CSharp/Deviations from Standard.md": "Deviations from the C# standard",
"_vblang/spec/introduction.md": "Introduction",
"_vblang/spec/lexical-grammar.md": "Lexical grammar",
Expand Down Expand Up @@ -819,10 +823,12 @@
"_csharplang/proposals/csharp-14.0/ignored-directives.md": "This proposal allows a source file to include ignored directives. In most cases, ignored directives are used for file-based apps, for example `#!`",
"_csharplang/proposals/csharp-14.0/extension-operators.md": "This proposal extends the proposal for extensions to include *extension operators*, where an operator can be an extension member.",
"_csharplang/proposals/csharp-14.0/optional-and-named-parameters-in-expression-trees.md": "This proposal allows an expression tree to include named and optional parameters. This enables expression trees to be more flexible in how they are constructed.",
"_csharplang/proposals/collection-expression-arguments.md": "This proposal introduces collection expression arguments.",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md": "Learn about any breaking changes since the initial release of C# 10 and included in C# 11",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md": "Learn about any breaking changes since the initial release of C# 11 and included in C# 12",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 9.md": "Learn about any breaking changes since the initial release of C# 12 and included in C# 13",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md": "Learn about any breaking changes since the initial release of C# 13 and included in C# 14",
"_roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 11.md": "Learn about any breaking changes since the initial release of C# 14 and included in C# 15",
"_roslyn/docs/compilers/CSharp/Deviations from Standard.md": "Learn about any deviations from the C# standard",
"_vblang/spec/introduction.md": "This chapter provides an overview of the Visual Basic language and its design goals.",
"_vblang/spec/lexical-grammar.md": "This chapter defines the lexical grammar for Visual Basic.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ms.custom: "updateeachrelease"

| Target | Version | C# language version default |
|------------------|---------|-----------------------------|
| .NET | 11.x | C# 15 |
| .NET | 10.x | C# 14 |
| .NET | 9.x | C# 13 |
| .NET | 8.x | C# 12 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ ms.custom: "updateeachrelease"
| `preview` | The compiler accepts all valid language syntax from the latest preview version. |
| `latest` | The compiler accepts syntax from the latest released version of the compiler (including minor version). |
| `latestMajor`<br>or `default` | The compiler accepts syntax from the latest released major version of the compiler. |
| `15.0` | The compiler accepts only syntax that is included in C# 15 or lower. |
| `14.0` | The compiler accepts only syntax that is included in C# 14 or lower. |
| `13.0` | The compiler accepts only syntax that is included in C# 13 or lower. |
| `12.0` | The compiler accepts only syntax that is included in C# 12 or lower. |
Expand Down
4 changes: 2 additions & 2 deletions docs/csharp/language-reference/language-versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Language versioning
description: Learn about how the C# language version is determined based on your project and the reasons behind that choice.
ms.custom: "updateeachrelease"
ms.date: 01/16/2026
ms.date: 02/04/2026
---

# C# language versioning
Expand All @@ -11,7 +11,7 @@ The latest C# compiler determines a default language version based on your proje

[!INCLUDE[csharp-version-note](./includes/initial-version.md)]

[C# 14](../whats-new/csharp-14.md) is supported only on .NET 10 and newer versions. [C# 13](../whats-new/csharp-13.md) is supported only on .NET 9 and newer versions. [C# 12](../whats-new/csharp-12.md) is supported only on .NET 8 and newer versions. Using a C# language version newer than the version associated with your target TFM is unsupported.
[C# 15](../whats-new/csharp-15.md) is supported only on .NET 11 and newer versions. [C# 14](../whats-new/csharp-14.md) is supported only on .NET 10 and newer versions. [C# 13](../whats-new/csharp-13.md) is supported only on .NET 9 and newer versions. Using a C# language version newer than the version associated with your target TFM is unsupported.

For details on which .NET versions are supported by versions of Visual Studio, see the [Visual Studio platform compatibility](/visualstudio/releases/2026/compatibility#-visual-studio-support-for-net-development) page.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Collection expressions (Collection literals)"
description: Collection expressions convert to many collection types. You can write literal values, expressions, or other collections to create a new collection.
ms.date: 01/20/2026
ms.date: 02/04/2026
helpviewer_keywords:
- "Collection expressions"
---
Expand Down Expand Up @@ -68,18 +68,18 @@ When you convert a collection expression to a `Span` or `ReadOnlySpan`, the span

## Collection builder

Collection expressions work with any collection type that's *well-behaved*. A well-behaved collection has the following characteristics:
Collection expressions work with any collection type that is *well-behaved*. A well-behaved collection has the following characteristics:

- The value of `Count` or `Length` on a [countable](./member-access-operators.md#index-from-end-operator-) collection produces the same value as the number of elements when enumerated.
- The types in the <xref:System.Collections.Generic?displayProperty=fullName> namespace are presumed to be side-effect free. As such, the compiler can optimize scenarios where such types might be used as intermediary values, but otherwise aren't exposed.
- A call to some applicable `.AddRange(x)` member on a collection results in the same final value as iterating over `x` and adding all of its enumerated values individually to the collection with `.Add`.
- The types in the <xref:System.Collections.Generic?displayProperty=fullName> namespace are side-effect free. The compiler can optimize scenarios where these types might be used as intermediary values, but it doesn't expose them otherwise.
- A call to an applicable `.AddRange(x)` member on a collection results in the same final value as iterating over `x` and adding all of its enumerated values individually to the collection by using `.Add`.

All the collection types in the .NET runtime are well-behaved.

> [!WARNING]
> If a custom collection type isn't well-behaved, the behavior is undefined when you use that collection type with collection expressions.

Your types opt in to collection expression support by writing a `Create()` method and applying the <xref:System.Runtime.CompilerServices.CollectionBuilderAttribute?displayProperty=fullName> on the collection type to indicate the builder method. For example, consider an application that uses fixed length buffers of 80 characters. That class might look something like the following code:
Your types opt in to collection expression support by writing a `Create()` method and applying the <xref:System.Runtime.CompilerServices.CollectionBuilderAttribute?displayProperty=fullName> attribute on the collection type to indicate the builder method. For example, consider an application that uses fixed length buffers of 80 characters. That class might look something like the following code:

:::code language="csharp" source="./snippets/shared/CollectionExpressionExamples.cs" id="BufferDeclaration":::

Expand All @@ -91,10 +91,61 @@ The `LineBuffer` type implements `IEnumerable<char>`, so the compiler recognizes

:::code language="csharp" source="./snippets/shared/CollectionExpressionExamples.cs" id="BuilderClass":::

The `Create` method must return a `LineBuffer` object, and it must take a single parameter of the type `ReadOnlySpan<char>`. The type parameter of the `ReadOnlySpan` must match the element type of the collection. A builder method that returns a generic collection has the generic `ReadOnlySpan<T>` as its parameter. The method must be accessible and `static`.
The `Create` method must return a `LineBuffer` object, and it must take a final parameter of the type `ReadOnlySpan<char>`. The type parameter of the `ReadOnlySpan` must match the element type of the collection. A builder method that returns a generic collection has the generic `ReadOnlySpan<T>` as its parameter. The method must be accessible and `static`.

Starting in C# 15, the `Create` method can have additional parameters before the `ReadOnlySpan<T>` parameter. You can pass values to these parameters by using a `with(...)` element in the collection expression. See [Collection builder arguments](#collection-builder-arguments) for details.

Finally, you must add the <xref:System.Runtime.CompilerServices.CollectionBuilderAttribute> to the `LineBuffer` class declaration:

:::code language="csharp" source="./snippets/shared/CollectionExpressionExamples.cs" id="BuilderAttribute":::

The first parameter provides the name of the *Builder* class. The second attribute provides the name of the builder method.

## Collection expression arguments

Starting in C# 15, you can pass arguments to the underlying collection's constructor or factory method by using a `with(...)` element as the first element in a collection expression. This feature enables you to specify capacity, comparers, or other constructor parameters directly within the collection expression syntax. For more information, see the [collection expression arguments feature specification](~/_csharplang/proposals/collection-expression-arguments.md).

The `with(...)` element must be the first element in the collection expression. The arguments declared in the `with(...)` element are passed to the appropriate constructor or create method based on the target type. You can use any valid expression for the arguments in the `with` element.

### Constructor arguments

When the target type is a class or struct that implements <xref:System.Collections.IEnumerable?displayProperty=nameWithType>, the arguments in `with(...)` are evaluated and the results are passed to the constructor. The compiler uses overload resolution to select the best matching constructor:

:::code language="csharp" source="./snippets/shared/CollectionExpressionExamples.cs" id="WithArgumentsExamples":::

In the preceding example:

- The `List<string>` constructor with a `capacity` parameter is called with `values.Length * 2`.
- The `HashSet<string>` constructor with an <xref:System.Collections.Generic.IEqualityComparer%601?displayProperty=nameWithType> parameter is called with `StringComparer.OrdinalIgnoreCase`.
- For interface target types like <xref:System.Collections.Generic.IList%601?displayProperty=nameWithType>, the compiler creates a `List<T>` with the specified capacity.

### Collection builder arguments

For types with a <xref:System.Runtime.CompilerServices.CollectionBuilderAttribute?displayProperty=nameWithType>, the arguments declared in the `with(...)` element are evaluated and the results are passed to the create method *before* the `ReadOnlySpan<T>` parameter. This feature allows create methods to accept configuration parameters:

:::code language="csharp" source="./snippets/shared/CollectionExpressionExamples.cs" id="BuilderClassWithComparer":::

You can then use the `with(...)` element to pass the comparer:

:::code language="csharp" source="./snippets/shared/CollectionExpressionExamples.cs" id="WithBuilderArgumentsExample":::

The create method is selected using overload resolution based on the arguments provided. The `ReadOnlySpan<T>` containing the collection elements is always the last parameter.

### Interface target types

Several interface target types support collection expression arguments. The following table shows the supported interfaces and their applicable constructor signatures:

| Interface | Supported `with` elements |
|-----------|---------------------|
| <xref:System.Collections.Generic.IEnumerable%601>, <xref:System.Collections.Generic.IReadOnlyCollection%601>, <xref:System.Collections.Generic.IReadOnlyList%601> | `()` (empty only) |
| <xref:System.Collections.Generic.ICollection%601>, <xref:System.Collections.Generic.IList%601> | `()`, `(int capacity)` |

For <xref:System.Collections.Generic.IList%601> and <xref:System.Collections.Generic.ICollection%601>, the compiler uses a <xref:System.Collections.Generic.List%601?displayProperty=nameWithType> with the specified constructor.

### Restrictions

The `with(...)` element has the following restrictions:

- It must be the first element in the collection expression.
- Arguments can't have `dynamic` type.
- It's not supported for arrays or span types (`Span<T>`, `ReadOnlySpan<T>`).
Loading
Loading