-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Switch to primary constructors in IDE layer #68299
Switch to primary constructors in IDE layer #68299
Conversation
@jaredpar fyi. |
@@ -8,22 +8,16 @@ | |||
|
|||
namespace Microsoft.CodeAnalysis.Classification | |||
{ | |||
public readonly struct ClassifiedSpan : IEquatable<ClassifiedSpan> | |||
public readonly struct ClassifiedSpan(TextSpan textSpan, string classificationType) : IEquatable<ClassifiedSpan> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me see about updating the feature to support that afterwards!
_start = start; | ||
_length = length; | ||
} | ||
private readonly int[] _buffer = buffer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compiler will warn in that case. Assigning to field, but also using the parameter will warn about double storage :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracked here: https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-05-15.md#primary-constructors
LDM just approved it. Will be coming asap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕐
@@ -8,13 +8,10 @@ | |||
namespace Microsoft.CodeAnalysis.Remote | |||
{ | |||
[DataContract] | |||
internal readonly struct RemoteServiceCallbackId : IEquatable<RemoteServiceCallbackId> | |||
internal readonly struct RemoteServiceCallbackId(int id) : IEquatable<RemoteServiceCallbackId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AdditionalProperties = additionalProperties; | ||
CandidateReason = candidateReason; | ||
} | ||
public readonly CandidateReason CandidateReason = candidateReason; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove public field declarations and instead apply DataMember attributes to the generated fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. There is currently no way to get to the "Generated Fields" for primary constructors currently (we don't even guarantee they are fields on the type). There are future lang changes about being able to have a primary constructor, but be explicit if you want fields/props/etc. but they are not in 12.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't say [field: DataMember(...)]
on the parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not currently. but LDM def aware of the desire here. I'd expect something post C#12 on this. It's too useful/valuable IMO to not have a solution for.
_documentId = documentId ?? throw new ArgumentNullException(nameof(documentId)); | ||
_activate = activateIfAlreadyOpen; | ||
} | ||
private readonly DocumentId _documentId = documentId ?? throw new ArgumentNullException(nameof(documentId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ How does it know when to create a backing field for the parameter, and when to not create it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
➡️ Answered as part of https://github.com/dotnet/roslyn/pull/68299/files#r1203256887
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we never "create a backing field". The question is if we have to continue using the existing backing field, or if we can remove it. And the answer to that is "if the field is read/written in any way that would have differnet semantics from the parameter". A good example of that is simply:
public bool Equals(Whatever w)
=> _documentId == w._documentId;
Here, we cannot switch to a parameter, because then you cannot access the field anymore off of w
.
public (string type, string layer)[] Metadata | ||
=> _services.Select(s => (s.Metadata.ServiceType, s.Metadata.Layer)).ToArray(); | ||
=> services.Select(s => (s.Metadata.ServiceType, s.Metadata.Layer)).ToArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 I really don't like that the fields are breaking naming conventions. It's going to make IntelliSense super annoying it types because you won't be able to type _
to filter to fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're not fields (seriously. the language does not think of them as fields, or treat them in any way as fields). They are captured parameters :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are being used as a replacement for a field of the same purpose, so they are functionally equivalent. I predict this is going to be problematic for feature adoption due to the amount of code that needs to change as part of this (all references to a field with a _
prefix need to change in source control when they start referring to the captured parameter instead). Personally, I would rather not have primary constructors than to have the captures appear with this name.
b19d2a6
to
e492694
Compare
e522e46
to
b91e3c1
Compare
Blocked because of dotnet/roslyn-analyzers#6573. @sharwell @mavasani can you guys look into this. |
9af8b0d
to
bf45d87
Compare
@mavasani It looks like IDE0060 needs to be updated to understand primary constructors. Usages of PCs now results in tons of warnings like: C:\github\roslyn\src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\Options\OptionDefinition.cs(102,41): warning IDE0060: Remove unused parameter 'serializer' (https://docs.microsoft.com/dot |
0f68404
to
789f05b
Compare
@mavasani @akhera99 i'm still getting:
|
No description provided.