Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The C# compiler generates errors and warnings when you misuse record types. Record types provide built-in members that implement value-based equality. These diagnostics help you follow the rules for declaring and using record types.
- CS8851: 'type' defines 'Equals' but not 'GetHashCode'
- CS8857: The receiver of a
withexpression must have a non-void type. - CS8858: The receiver type 'type' is not a valid record type and is not a struct type.
- CS8859: Members named 'Clone' are disallowed in records.
- CS8860: Types and aliases should not be named 'record'.
- CS8864: Records may only inherit from object or another record.
- CS8865: Only records may inherit from records.
- CS8866: Record member 'member' must be a readable instance property or field of type 'type' to match positional parameter 'parameter'.
- CS8869: 'member' does not override expected method from 'object'.
- CS8870: 'member' cannot be sealed because containing record is not sealed.
- CS8871: 'member' does not override expected method from 'type'.
- CS8872: 'member' must allow overriding because the containing record is not sealed.
- CS8873: Record member 'member' must be public.
- CS8874: Record member 'member' must return 'type'.
- CS8875: Record member 'member' must be protected.
- CS8876: 'member' does not override expected property from 'type'.
- CS8877: Record member 'member' may not be static.
- CS8879: Record member 'member' must be private.
- CS8906: Record equality contract property 'member' must have a get accessor.
- CS8908: The type 'type' may not be used for a field of a record.
- CS8913: The positional member 'member' found corresponding to this parameter is hidden.
In addition, this article covers the following warning:
- CS8907: Parameter 'name' is unread. Did you forget to use it to initialize the property with that name?
Synthesized member signatures
- CS8869: 'member' does not override expected method from 'object'.
- CS8870: 'member' cannot be sealed because containing record is not sealed.
- CS8871: 'member' does not override expected method from 'type'.
- CS8872: 'member' must allow overriding because the containing record is not sealed.
- CS8873: Record member 'member' must be public.
- CS8874: Record member 'member' must return 'type'.
- CS8875: Record member 'member' must be protected.
- CS8876: 'member' does not override expected property from 'type'.
- CS8877: Record member 'member' may not be static.
- CS8879: Record member 'member' must be private.
- CS8906: Record equality contract property 'member' must have a get accessor.
When you explicitly declare a member that the compiler would otherwise synthesize for a record type, your declaration must match the expected signature, accessibility, and modifiers. For the complete rules, see the records specification in the C# language specification.
To correct these errors, apply the following changes to your explicitly declared record members:
- Change the accessibility of the
Equalsmethod,GetHashCode,ToString, the deconstruct method, and theEqualityContractproperty orop_Equalityandop_Inequalityoperators topublic. The compiler requires these members to be publicly accessible so that value-based equality works correctly across all calling contexts (CS8873). - Change the accessibility of the
PrintMembersmethod toprotectedwhen you declare it in a non-sealed record class. The method must beprotectedbecause derived records override it to include their own properties in the formatted output (CS8875). - Change the accessibility of the
PrintMembersmethod toprivatewhen you declare it in a sealed record class or a record struct. Because no derived type can exist, the method doesn't need to be accessible outside the type (CS8879). - Remove the
staticmodifier from any explicitly declared synthesized member. Synthesized members operate on specific record instances to implement behaviors like equality comparison, formatting, and copying, so they must be instance members (CS8877). - Change the return type of the member to match the type the compiler expects. For example, the
EqualityContractproperty must returnSystem.Type, and theEqualsmethod must returnbool. The compiler relies on these exact return types to generate correct code for equality and other synthesized behaviors (CS8874). - Remove the
sealedmodifier from any explicitly declared synthesized member in a non-sealed record. Derived records must be able to override these members to provide their own value-based equality and formatting logic (CS8870). - Declare explicitly provided synthesized members as
virtualoroverridein a non-sealed record. The compiler requires these members to allow overriding so that derived records in the inheritance hierarchy can customize their behavior (CS8872). - Ensure that your explicitly declared member overrides the expected method from
objector from the base record type. For example, theEqualsmethod must overrideobject.Equals, andGetHashCodemust overrideobject.GetHashCode. The compiler checks that these members participate in the correct override chain so that value-based equality and other synthesized behaviors work correctly across the type hierarchy (CS8869, CS8871). - Ensure that your explicitly declared
EqualityContractproperty overrides the base record'sEqualityContractproperty. The compiler relies on the override chain for the equality contract to distinguish record types at run time within the inheritance hierarchy (CS8876). - Add a
getaccessor to theEqualityContractproperty. The compiler reads the equality contract at run time to determine whether two record instances are of the same type, so the property must be readable (CS8906).
Positional members
- CS8866: Record member 'member' must be a readable instance property or field of type 'type' to match positional parameter 'parameter'.
- CS8907: Parameter 'name' is unread. Did you forget to use it to initialize the property with that name?
- CS8908: The type 'type' may not be used for a field of a record.
- CS8913: The positional member 'member' found corresponding to this parameter is hidden.
When you declare a positional record, the compiler synthesizes properties that correspond to each positional parameter. These diagnostics indicate that your explicit declarations conflict with those synthesized properties. For the complete rules, see the records specification in the C# language specification.
To correct these errors, apply the following changes to your positional record declarations:
- Change any explicitly declared member that corresponds to a positional parameter so it's a readable instance property or field with the same type as the parameter. The compiler needs the member to be readable and type-compatible so that the synthesized
Deconstructmethod and positional pattern matching can access the value correctly (CS8866). - Ensure that each positional parameter initializes its corresponding property in the constructor body when you provide an explicit constructor. The compiler raises a warning when a parameter goes unused because it typically indicates a typo or a mismatch between the parameter name and the property name, which would leave the property uninitialized (CS8907).
- Change the type of a field declared in a record to a type that's valid in that context. Certain types, such as
Span<T>or otherref structtypes, can't be used as fields in a record because record types require all fields to be compatible with heap allocation and value-based equality (CS8908). - Remove the
newmodifier from a member in a derived record that hides a positional member from the base record. When a positional member is hidden, the compiler can't match the positional parameter to its corresponding property, which breaks the synthesizedDeconstructmethod and positional pattern matching (CS8913).
Equality members
- CS8851: 'type' defines 'Equals' but not 'GetHashCode'
- CS8857: The receiver of a
withexpression must have a non-void type. - CS8858: The receiver type 'type' is not a valid record type and is not a struct type.
Record types provide built-in value-based equality. These diagnostics arise when your declarations conflict with the equality contract. For the complete rules on equality, see equality comparisons.
To correct these errors, apply the following changes:
- Add a
GetHashCodemethod whenever you define anEqualsmethod. The equality contract requires that objects considered equal produce the same hash code, so the compiler enforces that these two methods are always defined together (CS8851). - Change the receiver of a
withexpression so that it's a record type or a struct type. Thewithexpression creates a modified copy by using therecordcopy constructor, or value copy semantics forstructtypes (CS8858). - Ensure the receiver of a
withexpression has a non-void type. Thewithexpression produces a new copy of the receiver, so the receiver must evaluate to a value that can be copied (CS8857).
Record inheritance
- CS8864: Records may only inherit from object or another record
- CS8865: Only records may inherit from records.
Record class types follow specific inheritance rules. For the complete rules, see the records specification in the C# language specification.
To correct these errors, apply the following changes:
- Change the base type of a record class so that it inherits from
objector from another record class. Record types rely on compiler-synthesized members for equality and copying that are only compatible with other record types, so the compiler doesn't allow a record to inherit from a non-record class (CS8864). - Change a non-record class that inherits from a record class so that it's declared as a record class instead. Because record types synthesize equality, cloning, and other members that depend on a consistent inheritance chain, the compiler requires every type in the hierarchy to be a record class (CS8865). Record struct types can't participate in inheritance hierarchies beyond implementing interfaces.
Reserved member names
- CS8859: Members named 'Clone' are disallowed in records.
- CS8860: Types and aliases should not be named 'record'.
The compiler reserves certain names for use with record types. For the complete rules, see the records specification in the C# language specification.
To correct these errors, apply the following changes:
- Rename any member called
Clonein a record type to a different name. The compiler usesCloneinternally to implement the copy semantics forwithexpressions, so declaring your ownClonemember conflicts with the synthesized implementation (CS8859). - Rename any type or alias named
recordto a different name. Becauserecordis a contextual keyword used for declaring record types, naming a type or aliasrecordcreates ambiguity that can confuse both the compiler and developers reading the code (CS8860).