Conversation
1. **Create `fundamentals/types/tuples.md`** — New "Tuples and deconstruction" article replacing `anonymous-types.md` - Content: tier tip, tuple declaration with named elements, inferred element names (C# 7.1), tuples as return types, tuple deconstruction (tuple-specific parts merged from `deconstruct.md`), discards (brief, link to `discards.md`), tuple comparison `==`/`!=` (C# 7.3), `with` on tuples, brief "prefer tuples over anonymous types" note linking to language reference - Does NOT duplicate: full syntax reference (stays in `value-tuples.md`), user-defined `Deconstruct`/extension methods (stays in `deconstruct.md`) - Frontmatter: `ms.topic: concept`, `ai-usage: ai-assisted`, no `f1_keywords`/`helpviewer_keywords` 1. **Create `snippets/tuples/` directory** — `tuples.csproj` (net10.0) + `Program.cs` with all snippet regions. Uses Everyday C# features. *parallel with step 1* 1. **Delete `anonymous-types.md`** and **`snippets/anonymous-types/`** — replaced by tuples. *depends on steps 1–2*
1. **Revise `interfaces.md`** — Remove `helpviewer_keywords`, add `ms.topic: concept` + `ai-usage: ai-assisted` + tier tip. Keep: declaring, implementing (implicit/explicit), interface inheritance, internal interfaces. Trim: default interface members → link to advanced; static abstract → brief mention linking out. Update summary bullets. 1. **Update `snippets/interfaces/`** — `.csproj` to net10.0, modernize `interfaces.cs` with latest features. *depends on step 4*
1. **Revise `generics.md`** — Remove `f1_keywords`/`helpviewer_keywords`, add `ms.topic: concept` + `ai-usage: ai-assisted` + tier tip. Reframe around **consuming** generics (`List<T>`, `Dictionary<TKey,TValue>`, `Task<T>`, `Func<T,TResult>`). Add: type inference, basic constraints (`class`/`struct`/`new()`/base type, brief `Enum`/`Delegate`/`unmanaged`), collection expressions (C# 12) with spread `..`, dictionary expressions (C# 14), co-/contra-variance at consumption level (link to `covariance-contravariance/` for depth). Demote `GenericList<T>` authoring example to secondary. 1. **Update `snippets/generics/`** — `.csproj` to net10.0, rewrite `Program.cs` with consuming-focused examples. *depends on step 6*
1. **Update `docs/csharp/toc.yml`** — Change "Tuples and anonymous types" → "Tuples and deconstruction" pointing to `tuples.md`. Remove `# TODO: tuples` comment. 1. **Update `.openpublishing.redirection.csharp.json`** — Modify existing redirect (`programming-guide/.../anonymous-types.md` → `/dotnet/csharp/fundamentals/types/tuples`). Add new redirect (`fundamentals/types/anonymous-types.md` → `/dotnet/csharp/fundamentals/types/tuples`). Sort alphabetically. 1. **Update cross-references** — Fix links to `anonymous-types.md` in `csharp-version-history.md` and `value-tuples.md` to point to `tuples.md` or language reference.
There was a problem hiding this comment.
Pull request overview
This PR restructures Everyday C# “type system” documentation by introducing a dedicated tuples article, refocusing interfaces and generics articles for fundamentals readers, and updating cross-references, snippets, TOC, and redirects.
Changes:
- Replaces the former
anonymous-types.mdfundamentals article with a newtuples.mdfocused on tuples and deconstruction, and updates redirects/TOC. - Revises
interfaces.mdandgenerics.mdto emphasize common usage patterns, with refreshed snippets. - Updates many docs to repoint anonymous-types references, plus related redirects.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 30 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/standard/linq/project-anonymous-type.md | Updates “Anonymous Types” links to the new fundamentals target. |
| docs/standard/linq/concepts-terminology-functional-transformation.md | Updates anonymous-types reference link in terminology. |
| docs/standard/base-types/choosing-between-anonymous-and-tuple.md | Updates references to fundamentals anonymous-types page. |
| docs/fundamentals/code-analysis/style-rules/ide0050.md | Updates anonymous-types links referenced by the analyzer rule. |
| docs/fundamentals/code-analysis/style-rules/ide0037.md | Updates anonymous-types link in analyzer rule overview. |
| docs/fsharp/language-reference/anonymous-records.md | Updates link for C# anonymous types interop section. |
| docs/csharp/whats-new/csharp-version-history.md | Updates “Anonymous types” link in C# 3.0 feature list. |
| docs/csharp/toc.yml | Replaces the “Tuples and anonymous types” TOC entry with “Tuples and deconstruction”. |
| docs/csharp/programming-guide/classes-and-structs/object-and-collection-initializers.md | Updates link target for anonymous types reference. |
| docs/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables.md | Updates anonymous types links to new fundamentals target. |
| docs/csharp/programming-guide/classes-and-structs/how-to-use-implicitly-typed-local-variables-and-arrays-in-a-query-expression.md | Updates anonymous types reference link. |
| docs/csharp/programming-guide/classes-and-structs/how-to-return-subsets-of-element-properties-in-a-query.md | Updates “Anonymous Types” link in “See also”. |
| docs/csharp/programming-guide/classes-and-structs/access-modifiers.md | Updates “Anonymous types” link in “See also”. |
| docs/csharp/misc/cs0833.md | Updates “Anonymous Types” link in “See also”. |
| docs/csharp/misc/cs0746.md | Updates “Anonymous Types” link in “See also”. |
| docs/csharp/linq/standard-query-operators/join-operations.md | Updates “Anonymous types” link in “See also”. |
| docs/csharp/linq/standard-query-operators/index.md | Updates “Anonymous Types” link in “See also”. |
| docs/csharp/linq/get-started/features-that-support-linq.md | Updates “anonymous type” link in the anonymous types section. |
| docs/csharp/language-reference/statements/declarations.md | Updates anonymous types link in implicitly-typed locals discussion. |
| docs/csharp/language-reference/operators/with-expression.md | Updates anonymous types link in operand description. |
| docs/csharp/language-reference/operators/new-operator.md | Updates anonymous types link in “Instantiation of anonymous types”. |
| docs/csharp/language-reference/keywords/select-clause.md | Updates “Anonymous Types” link in “See also”. |
| docs/csharp/language-reference/builtin-types/value-tuples.md | Removes link to removed anonymous-types fundamentals page. |
| docs/csharp/fundamentals/types/tuples.md | Adds new fundamentals article for tuples and deconstruction. |
| docs/csharp/fundamentals/types/snippets/tuples/tuples.csproj | Retargets tuples snippet project to net10.0. |
| docs/csharp/fundamentals/types/snippets/tuples/Program.cs | Adds new tuples/deconstruction/equality/with/dictionary examples. |
| docs/csharp/fundamentals/types/snippets/interfaces/interfaces.csproj | Retargets interfaces snippet project to net10.0. |
| docs/csharp/fundamentals/types/snippets/interfaces/interfaces.cs | Reworks interface examples (implicit/explicit impl, inheritance, internal interfaces). |
| docs/csharp/fundamentals/types/interfaces.md | Rewrites the interfaces fundamentals article and references new snippets. |
| docs/csharp/fundamentals/types/snippets/generics/Program.cs | Reworks generics samples toward “consuming generics” and newer syntax examples. |
| docs/csharp/fundamentals/types/snippets/generics/generics.csproj | Retargets generics snippet project to net10.0 and removes explicit startup object. |
| docs/csharp/fundamentals/types/snippets/anonymous-types/Program.cs | Removes old anonymous-types snippet program (file deleted). |
| docs/csharp/fundamentals/types/generics.md | Rewrites generics fundamentals article and references new snippets. |
| docs/csharp/fundamentals/types/anonymous-types.md | Removes old fundamentals anonymous types article (file deleted). |
| docs/csharp/fundamentals/object-oriented/index.md | Updates anonymous types section to point to tuples article. |
| docs/core/diagnostics/diagnosticsource-diagnosticlistener.md | Updates anonymous-type link in DiagnosticSource payload guidance. |
| .openpublishing.redirection.csharp.json | Adds/updates redirects from removed anonymous-types pages to the new tuples page. |
Comments suppressed due to low confidence (1)
docs/csharp/misc/cs0833.md:42
- The “Anonymous Types” reference now links to
fundamentals/types/tuples.md, but this compiler error is specifically about anonymous types. Link to anonymous-type documentation (or add an anchor/section in the destination) so the reference matches the error topic.
## See also
- [Anonymous Types](../fundamentals/types/tuples.md)
docs/csharp/fundamentals/types/snippets/interfaces/interfaces.cs
Outdated
Show resolved
Hide resolved
docs/csharp/fundamentals/types/snippets/interfaces/interfaces.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…agner/docs into tuples-interfaces-generics
Recreate the anonymous types article in the programming guide section.
Update links to the new anonymous types article, or both the tuples and anonymous types article.
|
@adegeo This is ready for final review. |
|
|
||
| :::code language="csharp" source="snippets/generics/Program.cs" ID="GenericCollections"::: | ||
|
|
||
| Generic collections prevent type errors at compile time rather than at runtime. They also avoid boxing for value types, which improves performance. |
There was a problem hiding this comment.
This doesn't read quite right as is.
| Generic collections prevent type errors at compile time rather than at runtime. They also avoid boxing for value types, which improves performance. | |
| Generic collections prevent type errors at runtime because the errors surface at compile time instead. These collections also avoid boxing for value types, which improves performance. |
| :::code language="csharp" source="./snippets/interfaces/interfaces.cs" ID="ImplementEquatable"::: | ||
|
|
||
| Any class or struct that implements the <xref:System.IEquatable`1> interface must contain a definition for an <xref:System.IEquatable`1.Equals*> method that matches the signature that the interface specifies. As a result, you can count on a class of type `T` that implements `IEquatable<T>` to contain an `Equals` method with which an instance of this class can determine whether it's equal to another instance of the same class. | ||
| Any class or struct that implements <xref:System.IEquatable`1> must provide an `Equals` method matching the interface signature. You can count on any `IEquatable<T>` implementation to support equality comparison, regardless of the concrete type. That predictability is the core value of interfaces. |
There was a problem hiding this comment.
| Any class or struct that implements <xref:System.IEquatable`1> must provide an `Equals` method matching the interface signature. You can count on any `IEquatable<T>` implementation to support equality comparison, regardless of the concrete type. That predictability is the core value of interfaces. | |
| Any class or struct that implements <xref:System.IEquatable`1> must provide an `Equals` method that matches the interface signature. You can count on any `IEquatable<T>` implementation to support equality comparison, regardless of the concrete type. That predictability is the core value of interfaces. |
There was a problem hiding this comment.
-ing words are more amiguous
|
|
||
| ## Interface inheritance | ||
|
|
||
| Interfaces can inherit from one or more other interfaces. A class implementing a derived interface must implement all members from the derived interface and all of its base interfaces: |
There was a problem hiding this comment.
| Interfaces can inherit from one or more other interfaces. A class implementing a derived interface must implement all members from the derived interface and all of its base interfaces: | |
| Interfaces can inherit from one or more other interfaces. A class that implements a derived interface must implement all members from the derived interface and all of its base interfaces: |
| - **Default interface members** let an interface provide a method body. Implementing types inherit the default implementation and can optionally override it. For more information, see [default interface methods](../../advanced-topics/interface-implementation/default-interface-methods-versions.md). | ||
| - **Static abstract members** require implementing types to provide a static member, which is useful for defining operator contracts or factory patterns. For more information, see [static abstract members in interfaces](../../language-reference/keywords/interface.md#static-abstract-and-virtual-members). | ||
|
|
||
| Both features are covered in the advanced topics section. Most everyday interface usage involves the declaring and implementing patterns described earlier in this article. |
There was a problem hiding this comment.
What does the "advanced topics" section refer to, a section in the TOC?
There was a problem hiding this comment.
Did you mean to check this in?
|
|
||
| ## When to use tuples instead | ||
|
|
||
| For most new code, consider using [tuples](../../fundamentals/types/tuples.md#tuples-vs-anonymous-types) instead of anonymous types. Tuples provide better performance as value types, deconstruction support, and more flexible syntax. Anonymous types remain the better choice when you need expression tree support or reference-type semantics. For a detailed comparison, see [Choosing between anonymous and tuple types](../../../standard/base-types/choosing-between-anonymous-and-tuple.md). |
There was a problem hiding this comment.
| For most new code, consider using [tuples](../../fundamentals/types/tuples.md#tuples-vs-anonymous-types) instead of anonymous types. Tuples provide better performance as value types, deconstruction support, and more flexible syntax. Anonymous types remain the better choice when you need expression tree support or reference-type semantics. For a detailed comparison, see [Choosing between anonymous and tuple types](../../../standard/base-types/choosing-between-anonymous-and-tuple.md). | |
| For most new code, consider using [tuples](../../fundamentals/types/tuples.md#tuples-vs-anonymous-types) instead of anonymous types. As value types, tuples provide better performance. They also provide deconstruction support and more flexible syntax. Anonymous types remain the better choice when you need expression tree support or reference-type semantics. For a detailed comparison, see [Choosing between anonymous and tuple types](../../../standard/base-types/choosing-between-anonymous-and-tuple.md). |
| :::code language="csharp" source="snippets/with-expression/BasicExample.cs" ::: | ||
|
|
||
| The left-hand operand of a `with` expression can be a [record type](../builtin-types/record.md). It can also be a [structure type](../builtin-types/struct.md) or an [anonymous type](../../fundamentals/types/anonymous-types.md). | ||
| The left-hand operand of a `with` expression can be a [record type](../builtin-types/record.md). It can also be a [structure type](../builtin-types/struct.md), [tuple](../builtin-types/value-tuples.md), or an [anonymous type](../../programming-guide/classes-and-structs/anonymous-types.md). |
There was a problem hiding this comment.
| The left-hand operand of a `with` expression can be a [record type](../builtin-types/record.md). It can also be a [structure type](../builtin-types/struct.md), [tuple](../builtin-types/value-tuples.md), or an [anonymous type](../../programming-guide/classes-and-structs/anonymous-types.md). | |
| The left-hand operand of a `with` expression can be a [record type](../builtin-types/record.md). It can also be a [structure type](../builtin-types/struct.md), a [tuple](../builtin-types/value-tuples.md), or an [anonymous type](../../programming-guide/classes-and-structs/anonymous-types.md). |
| "redirections": [ | ||
| { | ||
| "source_path_from_root": "/docs/csharp/fundamentals/types/anonymous-types.md", | ||
| "redirect_url": "/dotnet/csharp/fundamentals/types/tuples" |
There was a problem hiding this comment.
Should this redirect to the new anonymous-types.md article instead and redirect document ID?
| > | ||
| > **Experienced in another language?** C# tuples are value types similar to tuples in Python or Swift, but with optional named elements and full deconstruction support. Skim the [deconstruction](#deconstruct-tuples) and [equality](#tuple-equality) sections for C#-specific patterns. | ||
|
|
||
| A *tuple* groups multiple values into a single, lightweight structure without requiring you to define a named type. Tuples are value types that you can declare inline, return from methods, and deconstruct into individual variables. Use tuples when you need a quick, temporary grouping of related values. For example, returning multiple results from a method or storing a coordinate pair. |
There was a problem hiding this comment.
| A *tuple* groups multiple values into a single, lightweight structure without requiring you to define a named type. Tuples are value types that you can declare inline, return from methods, and deconstruct into individual variables. Use tuples when you need a quick, temporary grouping of related values. For example, returning multiple results from a method or storing a coordinate pair. | |
| A *tuple* groups multiple values into a single, lightweight structure without requiring you to define a named type. Tuples are value types that you can declare inline, return from methods, and deconstruct into individual variables. Use tuples when you need a quick, temporary grouping of related values. For example, when you return multiple results from a method or store a coordinate pair. |
There was a problem hiding this comment.
Line 9's grammar isn't quite correct. Suggestion:
Since then, new options have been introduced with language -level support, such as xref:System.ValueTuple`2?displayProperty=nameWithType. As the names imply, these options provide a value type with the flexibility of anonymous types.
Fixes #51994
Replace
anonymous-types.mdwith a dedicatedtuples.mdfocused on tuples and deconstruction. Reviseinterfaces.mdto trim advanced content (default interface members, static abstract members). Revisegenerics.mdto shift from authoring to consuming generics and add collection expressions, dictionary expressions, spread, and co-/contra-variance. Update snippets, toc.yml, and redirects.Internal previews
Toggle expand/collapse
newoperator creates a new instance of a typeNote
This table shows preview links for the 30 files with the most changes. For preview links for other files in this PR, select OpenPublishing.Build Details within checks.