Skip to content

Document projection initializers (simplified names) for anonymous types #47709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 4, 2025
Merged
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
18 changes: 18 additions & 0 deletions docs/csharp/fundamentals/types/anonymous-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ If you don't specify member names in the anonymous type, the compiler gives the

:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="snippet81":::

## Projection initializers

Anonymous types support *projection initializers*, which allow you to use local variables or parameters directly without explicitly specifying the member name. The compiler infers the member names from the variable names. The following example demonstrates this simplified syntax:

:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="ProjectionInitializers":::

This simplified syntax is particularly useful when creating anonymous types with many properties:

:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="ProjectionExample":::

The member name isn't inferred in the following cases:

- The candidate name is a member name of an anonymous type, such as `ToString` or `GetHashCode`.
- The candidate name is a duplicate of another property member in the same anonymous type, either explicit or implicit.
- The candidate name isn't a valid identifier (for example, it contains spaces or special characters).

In these cases, you must explicitly specify the member name.

> [!TIP]
> You can use .NET style rule [IDE0037](../../../fundamentals/code-analysis/style-rules/ide0037.md) to enforce whether inferred or explicit member names are preferred.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ class Anonymous
{
static void Main()
{
// don't show this unless you add a bunch more
// properties to the type. otherwise it obviates the
// need for the anonymous type
// Don't show this unless you add a bunch more
// properties to the type. Otherwise it obviates the
// need for the anonymous type.
List<Product> products = new ()
{
new Product() { Color="Orange", Price=2.00M},
Expand Down Expand Up @@ -50,6 +50,34 @@ from prod in products
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };
// </Snippet03>

// <ProjectionInitializers>
// Explicit member names.
var personExplicit = new { FirstName = "Kyle", LastName = "Mit" };

// Projection initializers (inferred member names).
var firstName = "Kyle";
var lastName = "Mit";
var personInferred = new { firstName, lastName };

// Both create equivalent anonymous types with the same property names.
Console.WriteLine($"Explicit: {personExplicit.FirstName} {personExplicit.LastName}");
Console.WriteLine($"Inferred: {personInferred.firstName} {personInferred.lastName}");
// </ProjectionInitializers>

// <ProjectionExample>
var title = "Software Engineer";
var department = "Engineering";
var salary = 75000;

// Using projection initializers.
var employee = new { title, department, salary };

// Equivalent to explicit syntax:
// var employee = new { title = title, department = department, salary = salary };

Console.WriteLine($"Title: {employee.title}, Department: {employee.department}, Salary: {employee.salary}");
// </ProjectionExample>
}
}
}