dotnet / dotnet/csharplang

[Proposal]: method attribute target for records for targeting primary constructor

Open
#7,047 11 comments 12 reactions 1 assignee Claimed by @RikkiGibson View on GitHub
Implemented Needs ECMA Spec Proposal Proposal champion
Dominant language
C#
Stars
12.7k
Forks
1.1k
Avg merge
11h 1m
Merged PRs (30d)
3

Description

# Allow "method" as an attribute target for records and record structs for targeting the primary constructor

* [x] Proposed
* [x] Prototype: ?
* [x] Implementation: Done, implemented in released version of C# 12
* [ ] Specification: ?

## Summary
It should be possible to specify that an attribute targets the primary constructor of a record/record struct, e.g.
```cs
[method: Attr]
public record Rec(
[property: Foo] int X,
[field: NonSerialized] int Y
);
```

## Motivation
There is currently no way to add attributes to the auto generated primary constructor when declaring records. This is needed for example to add JsonConstructorAttribute to specify which constructor json serializers should use when deserializing a record type with additional constructors. (both System.Text.Json and Newtonsoft.Json has this). See also discussion at #3650

## Detailed design
The "method" attribute target should be allowed on records and record structs and would result in the generated primary constructor (but not the generated copy constructor) having that attribute. Explicitly declared constructors are unaffected.

Attributes with the `method` target are only allowed on declarations specifying the primary constructor. They are ignored with a warning when used with declarations without a parameter list:
```cs
[method: FooAttr] // Good
public partial record Rec(
[property: Foo] int X,
[field: NonSerialized] int Y
);

[method: BarAttr] // warning CS0657: 'method' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'type'. All attributes in this block will be ignored.
public partial record Rec
{
public void Frobnicate()
{
...
}
}

[method: Attr] // Good
public record MyUnit1();

[method: Attr] // warning CS0657: 'method' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'type'. All attributes in this block will be ignored.
public record MyUnit2;
```

## Drawbacks
Still no way to target the copy constructor. Also "method" may be a bit confusing as opposed to adding a new "constructor" target.

## Alternatives
* Add a new "constructor" attribute target with the same functionality.
* Make the attribute target both the primary and the copy constructor (this does not solve the problem with adding JsonConstructorAttribute though)

## Unresolved questions

## Design meetings

* https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-03-13.md#attributes-on-primary-ctors

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.