From b811584eb8350fdaae4fca407a1800e0f8e18b45 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 24 Jan 2026 11:08:26 -0500 Subject: [PATCH 1/2] support record with sealed ToString Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 21570b74-c6f5-4fc5-ab6d-7546918d6ddb --- standard/classes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/standard/classes.md b/standard/classes.md index ee8602252..e1130acd3 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -6331,7 +6331,9 @@ The record class shall include a provided method method declared as follows: public override string ToString(); ``` -The method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record class type is not sealed. It is an error if either provided, or explicitly declared, method doesn't override `object.ToString()` (for example, due to shadowing in intermediate base types). +The method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record class type is not sealed. It is an error if either the provided or explicitly declared method doesn't override `object.ToString()` (for example, due to shadowing in intermediate base types). + +Sealing an explicitly declared `ToString` method prevents the compiler from providing a `ToString` method for any derived record types. However, this does not prevent the compiler from providing `PrintMembers`. The provided method: From bf362d762907f8f952e284bbdbdf4dd01d3e9058 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 28 Oct 2026 16:31:12 -0400 Subject: [PATCH 2/2] Modify sealed record `ToString` rules Allow sealed overrides on unsealed records and clarify synthesis and hiding when a base record seals object.ToString(). Add an inheritance example. --- standard/classes.md | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index e1130acd3..8a39e1eed 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -6325,15 +6325,15 @@ If the record class has no printable members, the method shall call the base `Pr The `PrintMembers` method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record class type is not sealed. -The record class shall include a provided method method declared as follows: +Unless a base record class declares a sealed override of `object.ToString()`, the record class shall include a provided method declared as follows: ```csharp public override string ToString(); ``` -The method may be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record class type is not sealed. It is an error if either the provided or explicitly declared method doesn't override `object.ToString()` (for example, due to shadowing in intermediate base types). +The method may be declared explicitly. When no base record class declares a sealed override of `object.ToString()`, it is an error if the explicit declaration does not match the expected signature or accessibility, or if either the provided or explicitly declared method doesn't override `object.ToString()` (for example, due to shadowing in intermediate base types). -Sealing an explicitly declared `ToString` method prevents the compiler from providing a `ToString` method for any derived record types. However, this does not prevent the compiler from providing `PrintMembers`. +When a base record class declares a sealed override of `object.ToString()`, the implementation shall not provide a `ToString` method for the derived record class. An explicitly declared `ToString` member in such a derived record class is subject to the ordinary rules for member hiding and overriding. Sealing `ToString` does not prevent the implementation from providing `PrintMembers`. The provided method: @@ -6343,6 +6343,34 @@ The provided method: 1. Appends `}`, 1. Returns the builder's contents with `builder.ToString()`. +> *Example*: An unsealed record class can seal its `ToString` override. A derived record class inherits that implementation instead of receiving a provided override: +> +> +> ```csharp +> record Base +> { +> public sealed override string ToString() => "Base"; +> } +> +> record Derived(int Value) : Base; +> +> class Program +> { +> static void Main() +> { +> Console.WriteLine(new Derived(1)); +> } +> } +> ``` +> +> The output is: +> +> ```console +> Base +> ``` +> +> *end example* +> > *Example*: Given the following: > >