Skip to content

Commit 31ede73

Browse files
Copilotmeaghanlewis
andcommitted
Add tuples comparison and guidance to anonymous types article
Co-authored-by: meaghanlewis <[email protected]>
1 parent e5e57d6 commit 31ede73

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

docs/csharp/fundamentals/types/anonymous-types.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ helpviewer_keywords:
1212

1313
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and isn't available at the source code level. The type of each property is inferred by the compiler.
1414

15+
> [!TIP]
16+
> In most scenarios, [tuples](../../language-reference/builtin-types/value-tuples.md) are the preferred choice over anonymous types. Tuples provide better performance, support deconstruction, and offer more flexible syntax. Use anonymous types primarily when you need expression tree support or when working with code that requires reference types.
17+
1518
You create anonymous types by using the [`new`](../../language-reference/operators/new-operator.md) operator together with an object initializer. For more information about object initializers, see [Object and Collection Initializers](../../programming-guide/classes-and-structs/object-and-collection-initializers.md).
1619

1720
The following example shows an anonymous type that is initialized with two properties named `Amount` and `Message`.
@@ -28,6 +31,43 @@ Anonymous types are typically used in the [`select`](../../language-reference/ke
2831

2932
Anonymous types contain one or more public read-only properties. No other kinds of class members, such as methods or events, are valid. The expression that is used to initialize a property can't be `null`, an anonymous function, or a pointer type.
3033

34+
## Anonymous types vs tuples
35+
36+
Both anonymous types and tuples let you group multiple values without defining a named type. However, tuples are the preferred choice in most scenarios because they provide better performance and more flexibility. The following table summarizes the key differences:
37+
38+
| Feature | Anonymous types | Tuples |
39+
|---------|----------------|--------|
40+
| Type | Reference type (`class`) | Value type (`struct`) |
41+
| Performance | Heap allocation | Stack allocation (better performance) |
42+
| Mutability | Read-only properties | Mutable fields |
43+
| Deconstruction | Not supported | Supported |
44+
| Expression trees | Supported | Not supported |
45+
| Access modifier | `internal` | `public` |
46+
| Member names | Required or inferred | Optional (with default names like `Item1`, `Item2`) |
47+
48+
### When to use tuples
49+
50+
Use tuples when:
51+
52+
- You need better performance through stack allocation.
53+
- You want to deconstruct values into separate variables.
54+
- You're returning multiple values from a method.
55+
- You don't need expression tree support.
56+
57+
The following example shows how tuples provide similar functionality to anonymous types with cleaner syntax:
58+
59+
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="TupleExample":::
60+
61+
### When to use anonymous types
62+
63+
Use anonymous types when:
64+
65+
- You're working with expression trees (for example, in some LINQ providers).
66+
- You need the object to be a reference type.
67+
- You're projecting query results in LINQ and want named properties without defining a class.
68+
69+
For more information about choosing between anonymous types and tuples, see [Choosing between anonymous and tuple types](../../../standard/base-types/choosing-between-anonymous-and-tuple.md).
70+
3171
The most common scenario is to initialize an anonymous type with properties from another type. In the following example, assume that a class exists that is named `Product`. Class `Product` includes `Color` and `Price` properties, together with other properties that you aren't interested in:
3272

3373
:::code language="csharp" source="snippets/anonymous-types/Program.cs" ID="ProductDefinition":::
@@ -93,3 +133,10 @@ var v = new { Title = "Hello", Age = 24 };
93133
94134
Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"
95135
```
136+
137+
## See also
138+
139+
- [Tuple types](../../language-reference/builtin-types/value-tuples.md)
140+
- [Choosing between anonymous and tuple types](../../../standard/base-types/choosing-between-anonymous-and-tuple.md)
141+
- [Object and Collection Initializers](../../programming-guide/classes-and-structs/object-and-collection-initializers.md)
142+
- [LINQ in C#](../../linq/index.md)

docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ from prod in products
7878

7979
Console.WriteLine($"Title: {employee.title}, Department: {employee.department}, Salary: {employee.salary}");
8080
// </ProjectionExample>
81+
82+
// <TupleExample>
83+
// Anonymous type example.
84+
var anonymousProduct = new { Name = "Widget", Price = 19.99M };
85+
Console.WriteLine($"Anonymous: {anonymousProduct.Name} costs ${anonymousProduct.Price}");
86+
87+
// Equivalent using a tuple with named elements.
88+
var tupleProduct = (Name: "Widget", Price: 19.99M);
89+
Console.WriteLine($"Tuple: {tupleProduct.Name} costs ${tupleProduct.Price}");
90+
91+
// Tuples support deconstruction.
92+
var (productName, productPrice) = tupleProduct;
93+
Console.WriteLine($"Deconstructed: {productName} costs ${productPrice}");
94+
// </TupleExample>
8195
}
8296
}
8397
}

0 commit comments

Comments
 (0)