Skip to content

Record types can seal ToString in C# 10. #24957

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 6 commits into from
Jul 6, 2021
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
2 changes: 1 addition & 1 deletion docs/csharp/language-reference/attributes/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The string provided as the first argument to the attribute constructor will be d

In C# 10, you can use constant string interpolation and the `nameof` operator to ensure the names match:

:::code language="csharp" source="snippets/ObsoleteExample.cs" ID="Snippet2" :::
:::code language="csharp" source="snippets/ObsoleteExample.cs" id="Snippet2" :::

## `AttributeUsage` attribute

Expand Down
7 changes: 5 additions & 2 deletions docs/csharp/language-reference/builtin-types/record.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Records - C# reference"
description: Learn about the record type in C#
ms.date: 02/25/2021
ms.date: 07/01/2021
f1_keywords:
- "record_CSharpKeyword"
helpviewer_keywords:
Expand Down Expand Up @@ -136,7 +136,7 @@ The `ToString` override creates a <xref:System.Text.StringBuilder> object with t

:::code language="csharp" source="snippets/shared/RecordType.cs" id="ToStringOverrideDefault":::

You can provide your own implementation of `PrintMembers` or the `ToString` override. Examples are provided in the [`PrintMembers` formatting in derived records](#printmembers-formatting-in-derived-records) section later in this article.
You can provide your own implementation of `PrintMembers` or the `ToString` override. Examples are provided in the [`PrintMembers` formatting in derived records](#printmembers-formatting-in-derived-records) section later in this article. In C# 10 and later, your implementation of `ToString` may include the `sealed` modifier, which prevents the compiler from synthesizing a `ToString` implementation for any derived records. Effectively, that means the `ToString` output will not include the runtime type information. (All members and values are displayed, because derived records will still have a PrintMembers method generated.)

## Inheritance

Expand Down Expand Up @@ -185,6 +185,9 @@ Here is an example of code that replaces the synthesized `PrintMembers` methods,

:::code language="csharp" source="snippets/shared/RecordType.cs" id="PrintMembersImplementation":::

> [!NOTE]
> In C# 10.0 and later, the compiler will synthesize `PrintMembers` when a base record has sealed the `ToString` method. You can also create your own implementation of `PrintMembers`.

### Deconstructor behavior in derived records

The `Deconstruct` method of a derived record returns the values of all positional properties of the compile-time type. If the variable type is a base record, only the base record properties are deconstructed unless the object is cast to the derived type. The following example demonstrates calling a deconstructor on a derived record.
Expand Down
4 changes: 3 additions & 1 deletion docs/csharp/whats-new/tutorials/records.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Use record types - C# tutorial
description: Learn about how to use record types, build hierarchies of records, and when to choose records over classes.
ms.date: 11/12/2020
ms.date: 07/01/2021
---
# Create record types

Expand Down Expand Up @@ -125,6 +125,8 @@ You declare a `PrintMembers` method in the `DegreeDays` record that doesn't prin

The signature declares a `virtual protected` method to match the compiler's version. Don't worry if you get the accessors wrong; the language enforces the correct signature. If you forget the correct modifiers for any synthesized method, the compiler issues warnings or errors that help you get the right signature.

In C# 10.0 and later, you can declare the `ToString` method as `sealed` in a record type. That prevents derived records from providing a new implementation. Derived records will still contain the `PrintMembers` override. You would do this if you didn't want the `ToString` method to display the runtime type of the record. In the preceding example, you'd lose the information on where the record was measuring heating or cooling degree days.

## Non-destructive mutation

The synthesized members in a positional record don't modify the state of the record. The goal is that you can more easily create immutable records. Look again at the preceding declarations for `HeatingDegreeDays` and `CoolingDegreeDays`. The members added perform computations on the values for the record, but don't mutate state. Positional records make it easier for you to create immutable reference types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>record_types</RootNamespace>
</PropertyGroup>

Expand Down