-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
New API: InitOnlyAttribute
#34978
Comments
I like this idea. I've got a situation where I'm dependency injecting a buffer into a specialized stream wrapper, which uses inversion of control. Without init-only, the interfaces have to keep a public getter/setter for the underlying stream, which isn't a huge issue but certainly causes a leaky abstraction that this would resolve. |
The proposed API you got allows it on Note that fields have |
Thanks. I fixed the proposed API to have |
Why do you need the attribute for fields? Why is not the existing |
Is the backing field really supposed to be ECMA-335 doesn't seem to allow this (emphasis mine):
|
You're not wrong, but the runtime doesn't fully enforce that restriction (use of the word "shall" means it's looser than "must"). In the recent .NET Language Standup it's said that they intend to exploit this fact that the runtime allows changing readonly instance fields without a problem in order to implement this feature. |
Right. Also, the ECMA-335 spec is not set in stone. It has been relaxed and augmented for number of other new runtime features. (We do not have a way to publish these edits today - but I hope that is going to change.) |
I'd be very nervous with any feature taking a dependency on initonly instance fields being mutable. That might tie our hands at making future optimizations. Recall that the core runtime forbids setting initonly static fields outside the cctor, even though the ECMA spec uses "shall" instead of "must". |
This makes the initonly instance fields mutable in a specific context only (only in methods tagged this attribute). I do not see why it would tie our hands at making future optimizations. |
Was the plan not also to allow this syntax? Did I misunderstand? class MyClass
{
public init readonly string PublicField;
// property below has its own compiler generated backing field
public string PublicProperty { get; init; }
}
var obj = new MyClass
{
PublicField = "hi!",
PublicProperty = "hello!"
}; |
I think we could omit [InitOnly] attribute from backing fields on auto-properties. But we would need it if bring back init-only fields (was in initial design, but is now out-of-scope). |
@GrabYourPitchforks Init-only fields were pushed out of scope for C# 9 in Monday's LDM discussion. Notes should be available shortly. We could add this back (in C# 9 or later) based on scenarios and feedback. |
Thanks all for the context - much appreciated! :) |
I very much prefer this approach first over depending on the aforementioned runtime quirk. 👍 |
namespace System.Runtime.CompilerServices
{
public sealed class IsExternalInit
{
}
} |
I share the concern that I think a better name would be |
Oh, apparently we missed that concern. Yeah, since @dotnet/fxdc, anybody else? |
|
Not sure if it will be a modreq or an actual attribute, but either way it will be turned into syntax in C#, so it will not be commonly visible. Did you have a better suggestion? I was just proposing staying away from |
Nah, @bartonjs is just disappointed that the name doesn't include ALL_CAPS or a crypto algorithm ;-) |
We discussed the unfortunate naming in relation to |
Personally I think that's the exact reason why it's a bad name. If it's mostly metadata-level visible (the only way you'll see it is if you're looking directly at metadata), it should use metadata-relevant names. Remember that we'll be encoding this into IL-verification, so this should become a part of a new metadata specification in the future. |
Is InitOnlyProperty_setAccessor going to be declared an accessor of InitOnlyProperty and marked special named? |
Regarding Validators and reflection: I presume that the implementation of validators will be something that's easily identifiable from metadata. Because of that, I think it'd make sense to at least allow reflection scenarios to explicitly call a validator, even if normal C# can't. A strawman of that may look something like this: public abstract partial class Type
{
public virtual void InvokeValidatorIfExists(object obj); //no-op if the type has no validator
} This can go out into a separate discussion if it comes to that, but since it briefly came up in the design meeting, I figured I'd put my 2 cents here first. |
@jcouv should answer this, but based on how I understand the compiler feature I'd expect that |
Metadata for the init accessor is being discussed in dotnet/csharplang#3376. |
@jcouv Is the IL called out above out of sync with the current design? Above states:
But on other threads, it appears to be:
|
Yes, the modreq was moved to the return type following API design review.
(Updated OP to reflect) |
Note: the proposed API was modified significantly during API design review.
See notes below: #34978 (comment)
The type will be used as a modreq on the return type of the set accessor:
public modreq(typeof(IsExternalInit) void set_InitOnlyProperty(string value) { ... }
Out-of-date:
As part of the C# 9 records feature, we want to allow some properties to be settable during "initialization". Initialization means construction and also object creation. So we would allow
new C() { InitOnlyProperty = "hello" }
.To declare such a property, we'll allow the following syntax:
We will emit this property as:
The attribute is used on the set accessor and in a modreq.
There are two potential expansion of the feature: init-only fields and init-only methods. We can discuss whether it is better to include those now, or add later.
So we are proposing to add the following API:
Tagging @jaredpar @agocke FYI
Updates:
The text was updated successfully, but these errors were encountered: