From 3d6c79199ab2b73163dd196de777ab4db4f241f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:56:41 +0000 Subject: [PATCH 1/4] Initial plan From 1c055f2313f93decb5a6f1391e6b7198d1098095 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 Aug 2025 20:03:35 +0000 Subject: [PATCH 2/4] Document projection initializers (simplified names) for anonymous types Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- .../fundamentals/types/anonymous-types.md | 18 ++++++++++++ .../types/snippets/anonymous-types/Program.cs | 28 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/docs/csharp/fundamentals/types/anonymous-types.md b/docs/csharp/fundamentals/types/anonymous-types.md index d86d624246787..70059d0b3a807 100644 --- a/docs/csharp/fundamentals/types/anonymous-types.md +++ b/docs/csharp/fundamentals/types/anonymous-types.md @@ -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 member name, 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. diff --git a/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs b/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs index 2b64b2cb05cda..6e94eb78c217e 100644 --- a/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs +++ b/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs @@ -50,6 +50,34 @@ from prod in products var shipment = new { address = "Nowhere St.", product }; var shipmentWithBonus = new { address = "Somewhere St.", product, bonus }; // + + // + // 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}"); + // + + // + 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}"); + // } } } From 885403d15d97bb421d19c337eebc7e3100cb1244 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:31:46 +0000 Subject: [PATCH 3/4] Clarify duplicate member name explanation for projection initializers Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- docs/csharp/fundamentals/types/anonymous-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/csharp/fundamentals/types/anonymous-types.md b/docs/csharp/fundamentals/types/anonymous-types.md index 70059d0b3a807..14ff13c4f8a6e 100644 --- a/docs/csharp/fundamentals/types/anonymous-types.md +++ b/docs/csharp/fundamentals/types/anonymous-types.md @@ -51,7 +51,7 @@ This simplified syntax is particularly useful when creating anonymous types with 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 member name, either explicit or implicit. +- 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. From 535b15bfb46b7e7d283134f1a396d9f86f6642a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:02:06 +0000 Subject: [PATCH 4/4] Add periods to code comments in anonymous types examples Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- .../types/snippets/anonymous-types/Program.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs b/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs index 6e94eb78c217e..4b665a0007a5b 100644 --- a/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs +++ b/docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs @@ -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 products = new () { new Product() { Color="Orange", Price=2.00M}, @@ -52,15 +52,15 @@ from prod in products // // - // Explicit member names + // Explicit member names. var personExplicit = new { FirstName = "Kyle", LastName = "Mit" }; - // Projection initializers (inferred member names) + // 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 + // Both create equivalent anonymous types with the same property names. Console.WriteLine($"Explicit: {personExplicit.FirstName} {personExplicit.LastName}"); Console.WriteLine($"Inferred: {personInferred.firstName} {personInferred.lastName}"); // @@ -70,7 +70,7 @@ from prod in products var department = "Engineering"; var salary = 75000; - // Using projection initializers + // Using projection initializers. var employee = new { title, department, salary }; // Equivalent to explicit syntax: